面向对象设计原则
-
开放封闭原则
尽量不修改代码前提下进行扩展
-
里氏替换原则
尽量不重写父类方法,若要重写应满足以下要求:
-
子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法
-
子类可以增加自己特有的方法
-
当子类的方法重载父类的方法时,方法的形参要比父类方法的输入参数更宽松
-
当子类的方法实现父类的抽象方法时,方法的返回值应比父类更严格
-
-
依赖倒置原则
- 高层模块不应该依赖底层模块,二者都应该依赖抽象。
- 抽象不应该依赖细节,细节应该依赖抽象。
- 依赖倒置的中心思想是面向接口编程。
-
接口隔离原则
不要在一个接口里面放很多的方法,这样会显得这个类很臃肿
- 客户端不应依赖它不需要的接口
- 类间的依赖关系应该建立在最小的接口上
-
单一职责原则
一个类只负责一项职责
创建型模式
工厂方法模式
优点
:
- 每一个具体产品对应一个工厂类,不需要修改工厂类代码
- 隐藏对象创建的内部细节
缺点
:
每增加一个产品类,就必须增加一个工厂类
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
原型模式
单例模式
保证一个类只有一个实例