设计模式

常见设计模式总结

面向对象设计原则

  1. 开放封闭原则

    尽量不修改代码前提下进行扩展

  2. 里氏替换原则

    尽量不重写父类方法,若要重写应满足以下要求:

    • 子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法

    • 子类可以增加自己特有的方法

    • 当子类的方法重载父类的方法时,方法的形参要比父类方法的输入参数更宽松

    • 当子类的方法实现父类的抽象方法时,方法的返回值应比父类更严格

  3. 依赖倒置原则

    • 高层模块不应该依赖底层模块,二者都应该依赖抽象。
    • 抽象不应该依赖细节,细节应该依赖抽象。
    • 依赖倒置的中心思想是面向接口编程。
  4. 接口隔离原则

    不要在一个接口里面放很多的方法,这样会显得这个类很臃肿

    • 客户端不应依赖它不需要的接口
    • 类间的依赖关系应该建立在最小的接口上
  5. 单一职责原则

    一个类只负责一项职责

创建型模式

工厂方法模式

优点:

  1. 每一个具体产品对应一个工厂类,不需要修改工厂类代码
  2. 隐藏对象创建的内部细节

缺点:

每增加一个产品类,就必须增加一个工厂类

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
class GreekLocalizer:
    """A simple localizer a la gettext"""

    def __init__(self) -> None:
        self.translations = {"dog": "σκύλος", "cat": "γάτα"}

    def localize(self, msg: str) -> str:
        """We'll punt if we don't have a translation"""
        return self.translations.get(msg, msg)


class EnglishLocalizer:
    """Simply echoes the message"""

    def localize(self, msg: str) -> str:
        return msg


def get_localizer(language: str = "English") -> object:

    """Factory"""
    localizers = {
        "English": EnglishLocalizer,
        "Greek": GreekLocalizer,
    }

    return localizers[language]()


def main():
    e, g = get_localizer(language="English"), get_localizer(language="Greek")
    for msg in "dog parrot cat bear".split():
         print(e.localize(msg), g.localize(msg))

抽象工厂模式

提供一个创建一系列相关或者相互依赖产品的接口

优点:

除工厂方法模式的优点之外,还有利于约束产品族

缺点:

扩展新的产品很麻烦

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
from typing import Type
from abc import abstractmethod, ABCMeta


class Pet(metaclass=ABCMeta):
    def __init__(self, name: str) -> None:
        self.name = name

    @abstractmethod
    def speak(self) -> None:
        pass

    @abstractmethod
    def __str__(self) -> str:
        pass


class Dog(Pet):
    def speak(self) -> None:
        print(f"<{self.name}>汪汪~")

    def __str__(self) -> str:
        return f"Dog<{self.name}>"


class Cat(Pet):
    def speak(self) -> None:
        print(f"<{self.name}>喵喵~")

    def __str__(self) -> str:
        return f"Cat<{self.name}>"


class PetShop:

    def __init__(self, animal_factory: Type[Pet]) -> None:
        self.pet_factory = animal_factory

    def buy_pet(self, name: str) -> Pet:
        pet = self.pet_factory(name)
        print(f"Here is your lovely {pet}")
        return pet


def main() -> None:
    cat_shop = PetShop(Cat)
    dog_shop = PetShop(Dog)

    pet1 = cat_shop.buy_pet("布偶")
    pet1.speak()

    pet2 = dog_shop.buy_pet("阿拉斯加")
    pet2.speak()
    

创建者模式

将一个复杂对象的创建于它的表示分离,使得同样的构建过程可以创建不同的表示

优点:

将构造代码与表示代码分开,可以精细控制构建过程

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
from abc import abstractmethod, ABCMeta


# 抽象建造者
class Building:
    def __init__(self) -> None:
        self.build_floor()
        self.build_size()

    @abstractmethod
    def build_floor(self):
        pass

    @abstractmethod
    def build_size(self):
        pass

    def __repr__(self) -> str:
        return "Floor: {0.floor} | Size: {0.size}".format(self)


# 具体建造者
class House(Building):
    def build_floor(self) -> None:
        self.floor = "One"

    def build_size(self) -> None:
        self.size = "Big"

# 具体建造者
class Flat(Building):
    def build_floor(self) -> None:
        self.floor = "More than One"

    def build_size(self) -> None:
        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:
    def __repr__(self) -> str:
        return "Floor: {0.floor} | Size: {0.size}".format(self)


class ComplexHouse(ComplexBuilding):
    def build_floor(self) -> None:
        self.floor = "One"

    def build_size(self) -> None:
        self.size = "Big and fancy"

# 指挥者
def construct_building(cls) -> Building:
    building = cls()
    building.build_floor()
    building.build_size()
    return building


def main():
    house = House()
    flat = Flat()
    print(house)
    print(flat)
    # Using an external constructor function:
    complex_house = construct_building(ComplexHouse)
    print(complex_house)

# output
Floor: One | Size: Big
Floor: More than One | Size: Small
Floor: One | Size: Big and fancy

原型模式

单例模式

保证一个类只有一个实例

结构型模式

适配器模式

桥模式

组合模式

装饰模式

外观模式

享元模式

代理模式

行为型模式

解释器模式

责任链模式

命令模式

迭代器模式

中介者模式

备忘录模式

观察者模式

状态模式

策略模式

访问者模式

模板方法模式