User or UserManager ? Problems of Observer Pattern

一首诗 newptcai at gmail.com
Fri Apr 3 13:34:34 EDT 2009


#This is a real world problem I met.
#
#We have a database containing serveral tables, like : user, role,
organization.  Each 2 of them has m:n relationships.  These relations
are stored in association tables.
#
#Not we have to load all these data in memory to gain higher
performances.  We create 3 classes , User, Role, Organization, to hold
these data.
#
#The question is : should I implement "add/delete/update" as methods
of User, or should I add another class UserManager?


#----------------
# Choice 1
#----------------

user_dict = {}
role_dict = {}

class User:
    on_del_funcs = []
    roles = []

    def del(self):
        user_dict.pop(self.name)

        for f in self.on_del_funcs:
            f(self)

    # Using Observer Pattern to notify this user is deleted.
    def addUserDelListener(self, on_del_func):
        on_del_funcs.append(on_del_funcs)

    def delUserDelListener(self, on_del_func):
        on_del_funcs.remove(on_del_func)

class Role:

    users = []

    def addUsser(self, user):
        self.users.append(user)
        user.roles.append(self)
        users.addUserDelListener(self.onUserDel)

    def onUserDel(self, user):
        self.users.remove(user)
        user.delUserDelListener(self.onUserDel)

#----------------
# Choice 2
#----------------

class UserManager:

    users = []

    @classmethod
    def delUser(cls, user):
        cls.users.remove(user)

        RoleManager.onUserDel(user)

class RoleManager:

    roles = []

    @classmethod
    def onUserDel(cls, user):
        for r in cls.roles.items():
            r.users.remove(user)


# These codes are not complete, but that's enough to show my question.
# The first choice, which use Observer Pattern, has a very big
problem.
# When calling addUserDelListener, user got not only a callback
function, it
# also add reference count of role.  So when we want to delete a
role.  We have
# to carefully remove all *listener* hold by other objects, otherwise
this role
# will never be garbage collected.

# Not a big problem for only 2 classes.  But when there are 10
*subject* classes which
# Role want to *observe*, 10 listeners has to be removed when delete a
role.
# And if these *subject* have 5 different types of events, then 50
listeners has
# to be removed.

# Actually I tried this approach once, and it is still a big headache
for 10
# programmers. ( The company I worked at that time hate any change to
so-called
# working code )



# The second choice, which I am using right now, actually has nothing
to do with
# Object Oriented Designing.   The manager classes are not real
classes, just
# container of methods.   These User/Role classes are only container
of data,
# not behavior.
#
# For many times, I asked my self, "Is it too hard for me to see the
power of
# OO, or I have just never met a problem suitable for a OO resolution?"



More information about the Python-list mailing list