设计模式是软件工程中解决特定问题的通用解决方案。这些模式提供了设计结构和最佳实践,帮助开发者创建灵活、可重用和可维护的代码。

设计模式分类

  • 创建型模式

用于描述"如何创建对象", 它的特点是“将对象的创建和使用分离”. 包括单例, 原型, 工厂方法, 抽象工厂, 建造者等创建型模式

  • 结构型模式

用于描述如何将类或对象按照某种布局组成更大的结构. 包括代理, 适配器, 桥接, 装饰, 外观, 享元, 组合等结构型模式

  • 行为型模式

用于描述类或对象之间怎样相互协作共同完成单个对象无法独立完成的任务, 以及怎样分配职责. 包括模板方法, 策略, 命令, 职责链, 状态, 观察者, 中介者, 迭代器, 访问者, 备忘录, 解释器等行为型模式

设计原则

开闭原则

对拓展开放, 对修改关闭. 在程序需要拓展的时候, 不能去修改原有的代码, 而应该是利用接口或抽象类进行实现或继承, 使得程序的拓展性更好, 易于维护

对于接口或抽象类, 只要抽象得合理, 基本上可以保持架构的稳定, 而具体细节又可以通过抽象类派生的实现类或接口的实现类来拓展

+---------------------+
| Shape |
+---------------------+
| + draw(): void |
+---------------------+
/\
||
+---------------------+ +---------------------+
| Circle | | Rectangle |
+---------------------+ +---------------------+
| + draw(): void | | + draw(): void |
+---------------------+ +---------------------+

里氏代换原则

任何基类出现的地方, 子类一定可以出现 . 即子类可以拓展父类的功能, 但是不能改变父类原有的功能, 子类除了增加新的方法完成新增功能外, 尽量不要重写父类方法

+---------------------+
| Bird |
+---------------------+
| + fly(): void |
+---------------------+
/\
||
+---------------------+ +---------------------+
| Sparrow | | Ostrich |
+---------------------+ +---------------------+
| + fly(): void | | + fly(): void |
+---------------------+ +---------------------+

单一职责原则

每一个类都应该只有一个职责, 也就是每个类只负责一件事情. 有助于减少类之间的耦合, 提高代码的可读性和可维护性

+----------------+
| UserManager |
+----------------+
| - addUser() |
| - removeUser() |
| - updateUser() |
+----------------+
| |
+----------------+

依赖倒转原则

高层模块不应该依赖低层模块, 两者都应该依赖于其抽象; 抽象不应该依赖于细节, 细节应该依赖于抽象. 有助于减少模块之间的耦合,增强系统的灵活性。

+---------------------+
| Service |
+---------------------+
| + operation(): void |
+---------------------+
/\
||
+---------------------+ +---------------------+
| ConcreteServiceA | | ConcreteServiceB |
+---------------------+ +---------------------+
| + operation(): void | | + operation(): void |
+---------------------+ +---------------------+

接口隔离原则

客户端不应该强迫依赖于它们不使用的方法

+---------------------+
| IShape |
+---------------------+
| + draw(): void |
+---------------------+
+---------------------+
| IColorable |
+---------------------+
| + color(): void |
+---------------------+
/\
||
+---------------------+ +---------------------+
| Square | | Circle |
+---------------------+ +---------------------+
| + draw(): void | | + draw(): void |
| + color(): void | | + color(): void |
+---------------------+ +---------------------+

组合优于继承

优先通过组合而不是继承来达到复用代码的目的

+---------------------+
| Engine |
+---------------------+
| + start(): void |
+---------------------+
||
||
+---------------------+
| Car |
+---------------------+
| - engine: Engine |
| + start(): void |
+---------------------+

迪米特原则

一个对象应该对其他对象有最少的了解. 每个模块不应该知道其他模块的内部细节, 对象之间应当通过严格定义的接口进行交互, 而不应该直接访问其他对象的内部结构

+---------------------+
| Customer |
+---------------------+
| + getName(): String |
+---------------------+
||
||
+---------------------+
| Order |
+---------------------+
| - customer: Customer|
| + getCustomerName():|
+---------------------+

避免重复原则

每一项知识在系统中都应该有一个唯一的、明确的、权威的表示. 目的是为了避免代码重复, 通过抽象和封装来减少冗余代码, 提高系统的可维护性和可拓展性

+---------------------+
| UserService |
+---------------------+
| - validateUser() |
| - saveUser() |
+---------------------+
/\
||
+----------------------------+ +---------------------+
| UserController | | UserRepository |
+----------------------------+ +---------------------+
| - userService: UserService |
+----------------------------+