组合与依赖注入

组合的场景出现在两个类需要协同工作的时候,这个时候需要考虑到解耦,不能让两个类之间有直接的关系,因为有可能有功能相似的类作用于第三个类里面

例如两个处理数据库的类功能相等,但是分为两个,如果Userinfo里面写死,就不能用第三个类了

实现原理:把一个对象当做参数传进来,而不是在该类的内部实例化,这样降低了类和类之间的耦合。

class SqlHelper:
    def get_one_data(self):
        pass
    def get_many_data(self):
        pass
    def get_all_data(self):
        pass
class MysqlHelper:
    def get_one_data(self):
        pass
    def get_many_data(self):
        pass
    def get_all_data(self):
        pass

class UserInfo:
    def __init__(self,helper):
        #self.sql = SqlHelper()
        self.sql = helper

    def login(self):
        #数据库操作
        self.sql.get_one_data()

    def user_list(self):
        self.sql.get_all_data()

h = SqlHelper()
obj = UserInfo(h)
obj.login()

  

另一种场景:

如果SQL函数还依赖一个类,即使用SQL类的时候同样的需要初始化一个类,然后把这个类当做参数传进来。

class foo:
    def f1(self):
        pass
    def f2(self):
        pass

class SqlHelper:
    def __init__(self,f):
        self.foo = f
    def get_one_data(self):
        self.foo.f1()
        pass
    def get_many_data(self):
        pass
    def get_all_data(self):
        pass
class MysqlHelper:
    def __init__(self,f):
        self.foo = f
    def get_one_data(self):
        pass
    def get_many_data(self):
        pass
    def get_all_data(self):
        pass

class UserInfo:
    def __init__(self,helper):
        #self.sql = SqlHelper()
        self.sql = helper

    def login(self):
        #数据库操作
        self.sql.get_one_data()

    def user_list(self):
        self.sql.get_all_data()

f = foo()
h = SqlHelper(f)
obj = UserInfo(h)
obj.login()

  

这样会出现的问题,架构越来越大,层级越来越盛,有没有一种方法可以省略掉之前的继承

使用组合依赖的方式实现,在类初始化之前在__new__方法之后把需要传入的参数加进来,这个类和对应的参数又放在

Mapper类里面来管理,细节如下:

class Mapper:
    __mapper_relation = {
        #'类':参数
    }
    @staticmethod
    def register(cls,value):   #注册类和参数
        Mapper.__mapper_relation[cls] = value

    @staticmethod
    def exist(cls):
        if cls in Mapper.__mapper_relation:
            return True
        return False

    @staticmethod
    def value(cls):
        return  Mapper.__mapper_relation[cls]

class MyType(type):
    """
    由于type类是C++实现的,所以创建一个类让它继承type,然后重写type的__call__方法
    后面创建的类再显式的指定需要继承的是MyType
    """
    def __call__(cls,*args,**kwargs):
        obj = cls.__new__(cls,*args,**kwargs)
        arg_list = list(args)
        if Mapper.exist(cls):
            value = Mapper.value(cls)
            arg_list.append(value)
        obj.__init__(*arg_list,**kwargs)
        return obj

class Foo():
    def f1(self):
        pass
    def f2(self):
        pass

class SqlHelper(metaclass=MyType):
    def __init__(self,f):
        self.foo = f
    def get_one_data(self):
        self.foo.f1()
        pass
    def get_many_data(self):
        pass
    def get_all_data(self):
        pass

class MysqlHelper(metaclass=MyType):
    def __init__(self,f):
        self.foo = f
    def get_one_data(self):
        pass
    def get_many_data(self):
        pass
    def get_all_data(self):
        pass

class UserInfo(metaclass=MyType):
    def __init__(self,helper):
        #self.sql = SqlHelper()
        self.sql = helper

    def login(self):
        #数据库操作
        self.sql.get_one_data()

    def user_list(self):
        self.sql.get_all_data()

# f = foo()
# h = SqlHelper(f)
# obj = UserInfo(h)
# obj.login()
#创建SqlHelper之前又要创建Foo对象
Mapper.register(SqlHelper,Foo())
#创建UserInfo之前需要创建SqlHelper或MysqlHelper对象使用Mapper注册
Mapper.register(UserInfo,SqlHelper())

#接下来实例化UesrInfo不需要传任何参数
obj= UserInfo()
print(obj.sql.foo)

  

posted @ 2018-07-23 00:26  梦中琴歌  阅读(338)  评论(0编辑  收藏  举报