Skip to content

knightsj/object-oriented-design

Repository files navigation

中文博客链接:

Catalogue & Link

Chapter 1:面向对象设计原则

缩写 英文名称 中文名称
SRP Single Responsibility Principle 单一职责原则
OCP Open Close Principle 开闭原则
LSP Liskov Substitution Principle 里氏替换原则
LoD Law of Demeter ( Least Knowledge Principle) 迪米特法则(最少知道原则)
ISP Interface Segregation Principle 接口分离原则
DIP Dependency Inversion Principle 依赖倒置原则

原则一:开闭原则(Open Close Principle)

定义

Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification.

即:一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。

定义的解读

  • 用抽象构建框架,用实现扩展细节。
  • 不以改动原有类的方式来实现新需求,而是应该以实现事先抽象出来的接口(或具体类继承抽象类)的方式来实现。

UML 类图对比

未实践开闭原则: 未实践开闭原则

实践了开闭原则: 实践了开闭原则

Demo

  1. 未实践开闭原则:OCPDemo1
  2. 实践了开闭原则:OCPDemo2

原则二:单一职责原则(Single Responsibility Principle)

定义

A class should have a single responsibility, where a responsibility is nothing but a reason to change.

即:一个类只允许有一个职责,即只有一个导致该类变更的原因。

定义的解读

  • 类职责的变化往往就是导致类变化的原因:也就是说如果一个类具有多种职责,就会有多种导致这个类变化的原因,从而导致这个类的维护变得困难。

  • 往往在软件开发中随着需求的不断增加,可能会给原来的类添加一些本来不属于它的一些职责,从而违反了单一职责原则。如果我们发现当前类的职责不仅仅有一个,就应该将本来不属于该类真正的职责分离出去。

  • 不仅仅是类,函数(方法)也要遵循单一职责原则,即:一个函数(方法)只做一件事情。如果发现一个函数(方法)里面有不同的任务,则需要将不同的任务以另一个函数(方法)的形式分离出去。

UML 类图对比

未实践单一职责原则: 未实践单一职责原则

实践了单一职责原则: 实践了单一职责原则

Demo

  1. 未实践单一职责原则:SRPDemo1
  2. 实践了单一职责原则:SRPDemo2

原则三:依赖倒置原则(Dependency Inversion Principle)

定义

  • Depend upon Abstractions. Do not depend upon concretions.
  • Abstractions should not depend upon details. Details should depend upon abstractions
  • High-level modules should not depend on low-level modules. Both should depend on abstractions.

即:

  • 依赖抽象,而不是依赖实现。
  • 抽象不应该依赖细节;细节应该依赖抽象。
  • 高层模块不能依赖低层模块,二者都应该依赖抽象。

定义解读

  • 针对接口编程,而不是针对实现编程。
  • 尽量不要从具体的类派生,而是以继承抽象类或实现接口来实现。
  • 关于高层模块与低层模块的划分可以按照决策能力的高低进行划分。业务层自然就处于上层模块,逻辑层和数据层自然就归类为底层。

UML 类图对比

未实践依赖倒置原则:

未实践依赖倒置原则

实践了依赖倒置原则: 实践了依赖倒置原则

Demo

  1. 未实践依赖倒置原则:DIPDemo1
  2. 实践了依赖倒置原则:DIPDemo2

原则四:接口分离原则(Interface Segregation Principle)

定义

Many client specific interfaces are better than one general purpose interface.

即:多个特定的客户端接口要好于一个通用性的总接口。

定义解读

  • 客户端不应该依赖它不需要实现的接口。
  • 不建立庞大臃肿的接口,应尽量细化接口,接口中的方法应该尽量少。

需要注意的是:接口的粒度也不能太小。如果过小,则会造成接口数量过多,使设计复杂化。

UML 类图对比

未实践接口分离原则: 未实践接口分离原则

实践了接口分离原则: 实践了接口分离原则

通过遵守接口分离原则,接口的设计变得更加简洁,而且各种客户类不需要实现自己不需要实现的接口。

Demo

  1. 未实践接口分离原则:ISPDemo1
  2. 实践了接口分离原则:ISPDemo2

原则五:迪米特法则(Law of Demeter)

定义

You only ask for objects which you directly need.

即:一个对象应该对尽可能少的对象有接触,也就是只接触那些真正需要接触的对象。

定义解读

  • 迪米特原则也叫做最少知道原则(Least Know Principle), 一个类应该只和它的成员变量,方法的输入,返回参数中的类作交流,而不应该引入其他的类(间接交流)。

UML 类图对比

未实践迪米特法则: 未实践迪米特法则

实践了迪米特法则: 实践了迪米特法则

很明显,在实践了迪米特法则的 UML 类图里面,没有了ClientGasEngine的依赖,耦合性降低。

Demo

  1. 未实践迪米特法则:LODDemo1
  2. 实践了迪米特法则:LODDemo2

原则六:里氏替换原则(Liskov Substitution Principle)

定义

In a computer program, if S is a subtype of T, then objects of type T may be replaced with objects of type S (i.e. an object of type T may be substituted with any object of a subtype S) without altering any of the desirable properties of the program (correctness, task performed, etc.)

即:所有引用基类的地方必须能透明地使用其子类的对象,也就是说子类对象可以替换其父类对象,而程序执行效果不变。

定义的解读

在继承体系中,子类中可以增加自己特有的方法,也可以实现父类的抽象方法,但是不能重写父类的非抽象方法,否则该继承关系就不是一个正确的继承关系。

UML 类图对比

未实践里氏替换原则:

未实践里氏替换原则

实践了里氏替换原则: 实践了里氏替换原则

Demo

  1. 未实践里氏替换原则:LSPDemo1
  2. 实践了里氏替换原则:LSPDemo2

Chapter 2:面向对象设计模式

2.1 创建型设计模式

创建型设计模式分为:

  1. 简单工厂模式(Simple Factory Pattern)
  2. 工厂方法模式(Factory Method Pattern)
  3. 抽象工厂模式(Abstract Factory Pattern)
  4. 单例模式(Singleton Pattern)
  5. 生成器模式(Builder Pattern)
  6. 原型模式(Prototype Pattern)

2.11 简单工厂模式

模式定义

简单工厂模式(Simple Factory Pattern):专门定义一个类(工厂类)来负责创建其他类的实例。可以根据创建方法的参数来返回不同类的实例,被创建的实例通常都具有共同的父类。

模式类图

简单工厂模式类图

Demo

2.12 工厂方法模式

模式定义

工厂方法模式(Factory Method Pattern)又称为工厂模式,工厂父类负责定义创建产品对象的公共接口,而工厂子类则负责生成具体的产品对象,即通过不同的工厂子类来创建不同的产品对象。

模式类图

工厂方法模式代码示例类图

Demo

工厂方法模式代码示例类图

2.13 抽象工厂模式

模式定义

抽象工厂模式(Abstract Factory Pattern):提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。

模式类图

抽象工厂模式类图

Demo

抽象工厂模式类图

2.14 单例模式

模式定义

单例模式(Singleton Pattern):单例模式确保某一个类只有一个实例,并提供一个访问它的全剧访问点。

模式类图

单例模式类图

Demo

2.15 生成器模式

模式定义

生成器模式(Builder Pattern):也叫创建者模式,它将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

模式类图

生成器模式类图

Demo

生成器模式代码示例类图

2.16 原型模式

模式定义

原型模式(Prototype Pattern): 使用原型实例指定待创建对象的类型,并且通过复制这个原型来创建新的对象。

模式类图

原型模式类图

Demo

原型模式代码示例类图

2.2 结构型设计模式

2.21 外观模式

模式定义

外观模式(Facade Pattern):外观模式定义了一个高层接口,为子系统中的一组接口提供一个统一的接口。外观模式又称为门面模式,它是一种结构型设计模式模式。

模式类图

外观模式类图

Demo

外观模式代码示例类图

2.22 适配器模式

模式定义

适配器模式(Adapter Pattern) :将一个接口转换成客户希望的另一个接口,使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。适配器模式的别名是包装器模式(Wrapper),是一种结构型设计模式。

模式类图

对象适配器模式:

适配器模式类图

类适配器模式: 类适配器模式类图

Demo

适配器模式代码示例类图

2.23 桥接模式

模式定义

桥接模式(Simple Factory Pattern):将抽象部分与它的实现部分分离,使它们都可以独立地变化。

模式类图

桥接模式类图

Demo

桥接模式代码示例类图

2.24 代理模式

模式定义

代理模式(Proxy Pattern) :为某个对象提供一个代理,并由这个代理对象控制对原对象的访问。

模式类图

代理模式类图

Demo

代理模式代码示例类图

2.25 装饰者模式

模式定义

装饰模式(Decorator Pattern) :不改变原有对象的前提下,动态地给一个对象增加一些额外的功能。

模式类图

装饰者模式类图

Demo

装饰者模式代码示例类图

2.26 享元模式

模式定义

享元模式(Flyweight Pattern):运用共享技术复用大量细粒度的对象,降低程序内存的占用,提高程序的性能。

模式类图

享元模式类图

Demo

享元模式代码示例类图

2.3 行为型设计模式

2.31 模板方法模式

模式定义

在模板模式(Template Method Pattern)中,定义一个操作中的算法的框架,而将一些步骤的执行延迟到子类中,使得子类可以在不改变算法的结构的前提下即可重新定义该算法的某些特定步骤。

模式类图

模板方法模式类图

Demo

模板方法模式代码示例类图

2.32 策略模式

模式定义

策略模式(Strategy Pattern):定义一系列算法,将每一个算法封装起来,并让它们可以相互替换。

模式类图

策略模式类图

Demo

策略模式代码示例类图

2.33 责任链模式

模式定义

责任链模式(Chain of Responsibility Pattern):为请求创建了一个接收者对象的链,每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推。

模式类图

责任链模式类图

Demo

2.34 状态模式

模式定义

在状态模式(State Pattern):允许一个对象在其内部状态改变时,改变它的行为。

模式类图

状态模式类图

Demo

状态模式代码示例类图

2.35 命令模式

模式定义

命令模式(Command Pattern):命令(或请求)被封装成对象。客户端将命令(或请求)对象先传递给调用对象。调用对象再把该命令(或请求)对象传给合适的,可处理该命令(或请求)的对象来做处理。

模式类图

命令模式类图

Demo

命令模式代码示例类图

2.36 观察者模式

模式定义

观察者模式(Observer Pattern):定义对象间的一种一对多的依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象都可以到通知并做相应针对性的处理。

模式类图

观察者模式类图

Demo

观察者模式代码示例类图

2.37 中介者模式

模式定义

中介者模式(Mediator Pattern):用一个中介对象来封装一系列的对象交互,中介者使各对象之间不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。

模式类图

状态模式类图

Demo

中介者模式代码示例类图

License

This repository is released under MIT License