05-05 结构类设计模式之适配器模式
______egon新书python全套来袭请看:https://egonlin.com/book.html
适配器模式
1适配器模式
适配器模式定义如下:将一个类的接口变换成客户端期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。适配器模式和装饰模式有一定的相似性,都起包装的作用,但二者本质上又是不同的,装饰模式的结果,是给一个对象增加了一些额外的职责,而适配器模式,则是将另一个对象进行了“伪装”。
适配器可以认为是对现在业务的补偿式应用,所以,尽量不要在设计阶段使用适配器模式,在两个系统需要兼容时可以考虑使用适配器模式。
import os
class Dog:
def __init__(self):
self.name ="Dog"
def bark(self): # bark :叫声
return "woof!" # woof 低吠声
class Cat:
def __init__(self):
self.name = "Cat"
def meow(self): # meow 猫叫声
return "meow" # meow 猫叫声
class Human:
def __init__(self):
self.name = "Human"
def speak(self):
return "hello, python"
class Car:
def __init__(self):
self.name = "Car"
def make_noise(self, noise_level):
return "noise level is {}".format(noise_level)
class Adapter: # adapter 适配器
def __init__(self,obj,adapted_methods): # adpted 适应
self.obj = obj
self.__dict__.update(adapted_methods) # self.__dict__是打印对象所有的属性,结果是一个字典 {"kye":value}
# key对应对象的属性,value对应属性的属性值。这里就相当于把不同类的方法都绑定到Adapter这个类实例化出来的
# 对象的make_noise 属性上面去,该属性的值对应其他类里面的方法。
def __getattr__(self, attr): # 当调用类不存的属性或者方法时,就会触发该魔法方法
return getattr(self.obj, attr) # getattr(object,attr [,default])
def main():
objects = []
dog = Dog()
objects.append(Adapter(dog,dict(make_noise=dog.bark)))
cat = Cat()
objects.append(Adapter(cat,dict(make_noise=cat.meow)))
human = Human()
objects.append(Adapter(human,dict(make_noise=human.speak)))
car = Car()
car_noise = lambda : car.make_noise(3)
objects.append(Adapter(car,dict(make_noise=car_noise)))
for obj in objects:
print("A",obj.name,"goes",obj.make_noise()) # 这里 obj.make_noise 就相当于 dog.bark 这些方法,后面加括号代表执行
print(obj.obj) # 原来的对象被存储到obj属性里面.
if __name__ == '__main__':
# 适配器模式在不改变原有类的基础上,统一了所有的方法,还能够保存原有对象的引用obj属性
main()
2适配器模式的优点和使用场景
优点:
1、适配器模式可以让两个接口不同,甚至关系不大的两个类一起运行;
2、提高了类的复用度,经过“伪装”的类,可以充当新的角色;
3、适配器可以灵活“拆卸”。
应用场景:
1、不修改现有接口,同时也要使该接口适用或兼容新场景业务中,适合使用适配器模式。例如,在一个嵌入式系统中,原本要将数据从Flash读入,现在需要将数据从磁盘读入,这种情况可以使用适配器模式,将从磁盘读入数据的接口进行“伪装”,以从Flash中读数据的接口形式,从磁盘读入数据。
3适配器模式的缺点
1、适配器模式与原配接口相比,毕竟增加了一层调用关系,所以,在设计系统时,不要使用适配器模式。