Skip to main content

Design patterns

· 6 min read

面向对象设计原则

  1. 开放封闭原则

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

  2. 里氏替换原则

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

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

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

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

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

  3. 依赖倒置原则

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

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

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

    一个类只负责一项职责

创建型模式

工厂方法模式

优点

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

缺点

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

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))


抽象工厂模式

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

优点

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

缺点

扩展新的产品很麻烦

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()

创建者模式

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

优点

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

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

原型模式

单例模式

保证一个类只有一个实例

结构型模式

适配器模式

桥模式

组合模式

装饰模式

外观模式

享元模式

代理模式

行为型模式

解释器模式

责任链模式

命令模式

迭代器模式

中介者模式

备忘录模式

观察者模式

状态模式

策略模式

访问者模式

模板方法模式