设计模式:面向对象设计原则

设计模式:面向对象设计原则

作者:wlai
发布:2019-12-01
更新:2025-02-09

一、重新认识(抽象层面的)面向对象

变化是软件复用的天敌!面向对象设计最大的优势是抵御变化!

  • (1)理解隔离变化

从宏观层面来看,面向对象的构建方式更能适应软件的变化,能将变化所带来的影响减为最小。

  • (2)各司其职

从微观层面来看,面向对象的方式更强调各个类的责任。由于需求变化导致的新增类型不应该影响原来类型的实现——即所谓的各负其责。

  • (3)对象是什么?

从语言实现层面来看,对象封装了代码和数据;从规格层面讲,对象是一系列可被使用的公共接口;从概念层面讲,对象是某种拥有责任的抽象

二、面向对象设计原则

2.1 依赖倒置原则(DIP)

(1)高层模块(稳定)不应该依赖于底层模块(变化),二者都应该依赖于抽象(稳定);

(2)抽象(稳定)不应该依赖于实现细节(变化),实现细节应该依赖于抽象(稳定);

分解与抽象

通过Shape这个抽象来隔离LineRect的变化!

2.2 开放封闭原则(OCP)

(1)对扩展开放,对更改封闭

(2)类模块应该是可扩展的,但是不可修改

2.3 单一职责原则(SRP)

(1)一个类应该仅有一个引起它变化的原因

(2)变化的方向隐含着类的责任

当一个类含有几十个成员变量或者方法时,往往说明你所设计的类可能承担了过多的职责。正常设计良好的类不会表现地如此臃肿。

2.4 Liskov替换原则(LSP)

(1)子类必须能够替换它们的基类(IS-A)

(2)继承表达类型抽象

当子类无法替换基类时,应该想一想子类和父类之间是否真的是继承关系?有没有可能它们之间是组合关系?

2.5 接口隔离原则(ISP)

(1)不应该强迫客户程序依赖它们不用的方法

(2)接口应该小而完备

接口应该小而完备意味着不要将不必要的方法暴露给用户程序

注:C++访问控制修饰符

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 Base {
public:
void func_public(void) {}

private:
void func_private(void) {}

protected:
void func_protected(void) {}
};

class Derived : public Base {
public:
void func1(void) {
func_public();
func_protected();
// func_private(); // 子类中不可访问父类的private方法
}
};

int main()
{
Base b;
b.func_public();
// b.func_private(); // 类对象中不可访问类的private方法
// b.func_protected(); // 类对象中不可访问类的protected方法

Derived d;
d.func1();
d.func_public();
// d.func_private(); // 子类对象中不可访问父类的private方法
// d.func_protected(); // 子类对象中不可访问父类的protected方法
}
修饰符 类内 子类类内 类对象 子类对象
public
private × × ×
protected × ×

2.6 优先使用对象组合,而不是类继承

(1)类继承通常为“白箱复用”,对象组合通常为“黑箱复用”

(2)继承在某种程度上破坏了封装性,子类父类耦合度过高

(3)而对象组合则要求被组合的对象具有良好定义的外部接口,耦合度低

2.7 封装变化点

(1)使用封装来创建对象之间的分界层,让设计者可以在分界层的一侧进行修改,而不会对另一侧产生不良影响从而实现分界之间的松耦合

2.8 针对接口编程,而不是针对实现编程

(1)不将变量类型声明为某个特定的具体类,而是声明为某个接口

(2)客户程序无需获知对象的具体类型,只需要知道对象所具有的接口

(3)减少系统中各部分的依赖关系,从而实现“高内聚低耦合”的类型设计方案

三、设计模式的分类

从封装变化的角度对设计模式进行分类,有以下几种:

(1)组件协作

  • Template Method

  • Strategy

  • Observer / Event

(2)单一职责

  • Decorator

  • Bridge

(3)对象创建

  • Factory Method

  • Abstract Factory

  • Prototype

  • Builder

(4)对象性能

  • Singleton

  • Flyweight

(5)接口隔离

  • Facade

  • Proxy

  • Mediator

  • Adapter

(6)状态变化

  • Memento

  • State

(7)数据结构

  • Composite

  • Iterator

  • Chain of

  • Responsibility

(8)行为变化

  • Command

  • Visitor

(9)领域问题

  • Interpreter

四、重构以获得模式

面向对象设计模式是“好的面向对象设计”,所谓“好的面向对象设计”指的是那些可以满足“应对变化,提高复用”的设计。

现代软件设计的特征是“需求的频繁变化”。设计模式的要点是“寻找变化的点,然后在变化点处应用设计模式,从而来更好地应对需求的变化”。“什么时候、什么地点应用设计模式”比“理解设计模式结构本身”更为重要。

设计模式的应用不宜先入为主,一上来就使用设计模式是对设计模式的最大误用。没有一步到位的设计模式。敏捷软件开发实践倡导的“Refactoring to Patterns”是目前普遍公认最好的使用设计模式的方法。

重构的关键技法

(1)静态绑定 –> 动态绑定

(2)早绑定 –> 晚绑定

(3)继承 –> 组合

(4)编译时依赖 –> 运行时依赖

(5)紧耦合 –> 松耦合


设计模式:面向对象设计原则
https://wlai.me/design-pattern-design-principles/
作者
wlai
发布于
2025年2月9日
许可协议