Categorisation

Category Explanation
Creational Patterns provide object creation mechanisms that increase flexibility and reuse of existing code.
Structural Patterns explain how to assemble objects and classes, while keeping the structures flexible and efficient.
Behavioral Patterns take care of effective communication and the assignment of responsibilities between objects.

Design Principle

  • Code Reuse
  • Extensibility

Encapsulation

Identify the aspects of your application that vary and separate them from what stays the same.

on Method Level

Before

1
2
3
4
5
6
7
8
9
10
11
12
def getOrderTotal(order):
total = 0
for item in order.items:
total += item.price * item.quantity

# 处理 tax 的逻辑和计算总价的逻辑放在一起了
if order.country == "US":
total += total * 0.07
elif order.country == "EU":
total += total * 0.2

return total

After

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
def getOrderTotal(order):
total = 0
for item in order.items:
total += item.price * item.quantity

# 处理 tax 的逻辑 与 计算总价的逻辑 拆开了
total += total * getTaxRate(order.country)

return total

def getTaxRate(country):
if country == "US":
return 0.07
elif country == "EU":
return 0.2
else:
return 0

on Class Level

随着项目进展,很有可能会在一个 method/class 里加入更多职责,而这些职责通常有属于自己的字段,这些添加的字段会逐渐模糊掉当前 method/class 原本的任务。

如想在 method 开头加入 auth 授权,那么如果直接写进 class,那么就需要在 class 内额外添加字段。

所以更好的解决办法是把不属于自己原本职责的内容拆分出去,拆分到一个新的 class 里去。

Program to Interface

Program to an interface, not an implementation. Depend on abstractions, not on concrete classes.

现在假设 class A 和 class B 需要通信。与其让 class A 的 method 里直接以 class B 为类型,最好使用 Interface 让其更加 flexible,以防后续需要对 class B 扩充(例如,不止接受 class B 为参数,还需要接受 class C 为参数)

  1. 找出 class A 里,究竟使用 B 里面的什么方法
  2. 把这些方法写成 interface 或者 abstract(virtual) class
  3. 让 class A 的参数接受的是实现了这个 interface 的 class(或者是 abstract class 的子类的 class)
  4. 接着让 class B 去实现这个 interface 或者继承这个 abstract class
如图所示,`Food` interface 让 `Cat` 不仅可以吃 `Sausage` 还可以接受其他食物
如图所示,Food interface 让 Cat 不仅可以吃 Sausage 还可以接受其他食物

Composition over Inheritance

Interface 有几个问题:

  1. subclass 必须继承所有 parent class 的 interface,不能只继承一个子集;且必须实现所有父类的 abstract 方法
  2. overriding 父类方法时,需要确保行为兼容
  3. 有时在实践中,父类需要知道子类的信息
  4. 父类子类耦合紧密,父类 method 的行为变化可能导致子类的行为变化
  5. 继承可能形成 parallel inheritance 结构

Inheritance 代表的是 “is a” 逻辑,而 Composition 代表的是 “has a” 逻辑。

Composition 与 Aggregation 逻辑也比较类似,其区别在于 life cycle 不同。Composition 中 component 与主体的 life cycle 相同(如汽车与引擎),而 Aggregation 中 components 的 life cycle 却不一定相同(如汽车与司机)。


SOLID Principle

  • Single Responsibility Principle
    • A class should have just one reason to change. 每个类只负责单一职责。
  • Open/Closed Principle
    • Classes should be open for extension but closed for modification. 尽量不修改原有代码,而是基于原有代码新增