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