组合的场景出现在两个类需要协同工作的时候,这个时候需要考虑到解耦,不能让两个类之间有直接的关系,因为有可能有功能相似的类作用于第三个类里面
例如两个处理数据库的类功能相等,但是分为两个,如果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)