python总共有23种设计模式
创作模式
- 工厂模式
- 抽象工厂模式
- 建设者模式
- 原型模式
- 单例模式
结构模式
- 适配器模式
- 装饰器模式
- 桥接模式
工厂模式
意图:
定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method 使一个类的实例化延迟到其子类。
适用性:
- 当一个类不知道它所必须创建的对象的类的时候。
- 当一个类希望由它的子类来指定它所创建的对象的时候。
- 当类将创建对象的职责委托给多个帮助子类中的某一个,并且你希望将哪一个帮助子类是代理者这一信息局部化的时候。
class GreekGetter(object): """A simple localizer a la gettext""" def __init__(self): self.trans = dict(dog="σκύλος", cat="γάτα") def get(self, msgid): """We'll punt if we don't have a translation""" return self.trans.get(msgid, str(msgid)) class EnglishGetter(object): """Simply echoes the msg ids""" def get(self, msgid): return str(msgid) def get_localizer(language="English"): """工厂的方法""" languages = dict(English=EnglishGetter, Greek=GreekGetter) return languages[language]() if __name__ == '__main__': # Create our localizers e, g = get_localizer(language="English"), get_localizer(language="Greek") # Localize some text for msgid in "dog parrot cat bear".split(): print(e.get(msgid), g.get(msgid))
细心的可能会发现,在工厂函数中去进行类的实例化,确实实现了类的创建和实例化的分离。但是如果有新需求的话,不但需要新增类,而且还需要修改工厂方法,增加对应类名。我们是否可以把工厂方法中的类名做进一步的抽象呢,这就是下面要说的抽象工厂模式。
抽象工厂模式
意图:
- 提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
适用性:
- 一个系统要独立于它的产品的创建、组合和表示时。
- 一个系统要由多个产品系列中的一个来配置时。
- 当你要强调一系列相关的产品对象的设计以便进行联合使用时。
- 当你提供一个产品类库,而只想显示它们的接口而不是实现时
import random class PetShop(object): """A pet shop""" def __init__(self, animal_factory=None): """pet_factory是我们的抽象工厂。我们可以随意设置它""" self.pet_factory = animal_factory def show_pet(self): """使用抽象工厂创建并显示宠物""" pet = self.pet_factory() print("We have a lovely {}".format(pet)) print("It says {}".format(pet.speak())) class Dog(object): def speak(self): return "woof" def __str__(self): return "Dog" class Cat(object): def speak(self): return "meow" def __str__(self): return "Cat" # Additional factories: # Create a random animal def random_animal(): """Let's be dynamic!""" return random.choice([Dog, Cat])() # Show pets with various factories if __name__ == "__main__": # A Shop that sells only cats cat_shop = PetShop(Cat) cat_shop.show_pet() print("") # A shop that sells random animals shop = PetShop(random_animal) for i in range(3): shop.show_pet() print("=" * 20)
我们看到了具体动物类(Dog, Cat等)以及接口的创建是独立的,动物相关功能的实现被完全抽象出来为一个类PetShop。这样就实现了类的创建和功能实现的解耦。
建设者模式
建设者模式使得复杂的对象的创建和它的表示实现解耦,所以同一个组织者Building可以用相同的流程(Building中方法),创建不同的对象(Hourse, Flat)。
意图:
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
适用性:
- 当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时。
- 当构造过程必须允许被构造的对象有不同的表示时。
# Abstract Building class Building(object): def __init__(self): self.build_floor() self.build_size() def build_floor(self): raise NotImplementedError def build_size(self): raise NotImplementedError def __repr__(self): return 'Floor: {0.floor} | Size: {0.size}'.format(self) # Concrete Buildings class House(Building): def build_floor(self): self.floor = 'One' def build_size(self): self.size = 'Big' class Flat(Building): def build_floor(self): self.floor = 'More than One' def build_size(self): self.size = 'Small' # In some very complex cases, it might be desirable to pull out the building # logic into another function (or a method on another class), rather than being # in the base class '__init__'. (This leaves you in the strange situation where # a concrete class does not have a useful constructor) class ComplexBuilding(object): def __repr__(self): return 'Floor: {0.floor} | Size: {0.size}'.format(self) class ComplexHouse(ComplexBuilding): def build_floor(self): self.floor = 'One' def build_size(self): self.size = 'Big and fancy' def construct_building(cls): building = cls() building.build_floor() building.build_size() return building # Client if __name__ == "__main__": house = House() print(house) flat = Flat() print(flat) # Using an external constructor function: complex_house = construct_building(ComplexHouse) print(complex_house)
第二个例子,相当于把第一个Building的逻辑抽出来了,实际上和第一个例子是一样的效果。
原型模式
意图:
用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
适用性:
- 当要实例化的类是在运行时刻指定时,例如,通过动态装载;
- 或者为了避免创建一个与产品类层次平行的工厂类层次时;
- 或者当一个类的实例只能有几个不同状态组合中的一种时。建立相应数目的原型并克隆它们可能比每次用合适的状态手工实例化该类更方便一些
class Prototype(object): value = 'default' def clone(self, **attrs): """Clone a prototype and update inner attributes dictionary""" # Python in Practice, Mark Summerfield obj = self.__class__() obj.__dict__.update(attrs) return obj class PrototypeDispatcher(object): def __init__(self): self._objects = {} def get_objects(self): """Get all objects""" return self._objects def register_object(self, name, obj): """Register an object""" self._objects[name] = obj def unregister_object(self, name): """Unregister an object""" del self._objects[name] def main(): dispatcher = PrototypeDispatcher() prototype = Prototype() d = prototype.clone() a = prototype.clone(value='a-value', category='a') b = prototype.clone(value='b-value', is_checked=True) dispatcher.register_object('objecta', a) dispatcher.register_object('objectb', b) dispatcher.register_object('default', d) print([{n: p.value} for n, p in dispatcher.get_objects().items()]) if __name__ == '__main__': main()
python装饰器模式
这种设计模式是什么?
装饰器模式主要用于动态的给一个对象(函数或者类等)添加新功能,而不改变原来的对象的实现方法。换句话说就是不能改变别人的代码,又能给别人的代码添加新功能。
它不同于继承,尤其是多继承涉及到的MRO,会大大增加了代码的发复杂度,而且不易理解。
下面我们来看看装饰器的一些示例
class Student: def __init__(self, name, age): self.name = name self.age = age def select_course(self): """选课""" print("%s select course" % self.name) def examination(self): """考试""" print("%s examination " % self.name) class Decorator: def __init__(self, name): self.name = name def attending_class(self): """上课""" print("student atten %s ding classes" % self.name.name) def __getattr__(self, item): return getattr(self.name, item) stu = Student("yn", "28") new_stu = Decorator(stu) new_stu.select_course() new_stu.examination() new_stu.attending_class()
输出结果如下:
yn select course
yn examination
student atten yn ding classes
下面我们简单分析一下执行流程,首先实例化Student类,产生对象stu,然后对Decorator进行实例化。下面开始对Decorator进行实例化,对Decorator进行实例化的时候,把stu作为参数Decorator类中name属性中。Decorator实例化之后产生对象为new_stu, 此时new_stu.name = stu。然后当调用new_stu.select_course()方法时,发现没有调用自身的__getattr__属性,返回的是getattr(stu, select_course),这时就相当于执行了stu.select_course()方法。依次类推。