Featured image of post 面向对象涉及模式

面向对象涉及模式

所有设计模式的总结及代码实现(TypeScript 版)

面向对象设计模式

  • 此文档为 TypeScript 版本,如果有面向对象的基础,稍微了解基本语法很容易看懂

  • 如果你是 Java 程序员,对应 Java 版本可以自己实现

面向对象编程范式中,我所了解的,设计模式一共有22种,常用的也就七八种。其中:简单工厂、工厂方法、抽象工厂 归为一种

在所有设计模式中,分为三大类型

创建型模式: 4种

对象的创建分离及解耦

其中,IOC(Inversion Of Control),也就是控制反转,是创建型模式的集大成者,也是最常见的

单例模式

顾名思义,一个对象被实例化多少次,最多只有一个实例

应用场景:需要频繁创建然后销毁的对象,或者需要生成唯一序列化环境,节省时空资源

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
// 饿汉式:实例化时就创建对象实例
class Singleton {
  private static instance: Singleton = new Singleton()
  private constructor() {}
  getInstance() {
    return Singleton.instance
  }
}

// 懒汉式:调用暴露的获取实例方法时创建实例
class Singleton {
	private instance: Singleton;
	private constructor(){};
	getInstance(){
        if(!this.instance) this.instance = new Singleton();
        return this.instance
    }
}

原型模式

往对象的原型上添加深度拷贝方法,这样可以直接复制一个已存在的实例而不是 new 新的实例

应用场景:用于创建耗时或者复杂的实例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
interface Prototype {
  clone(): Prototype
}

class Apple implements Prototype {
  constructor() {}
  clone(): Prototype {
    return Object.create(this)
  }
}

工厂模式

统一创建对象的方法

应用场景:多种复杂类的实例化的解耦

 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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
// 1、简单工厂模式:抽象类
abstract class Fruit {
   color: string
}
class Apple extends Fruit { }
class Banana extends Fruit { }
class FruitFactory {
  static createFruit(type: 'apple' | 'banana'): Fruit | null {
    if (type === 'apple') return new Apple()
    if (type === 'banana') return new Banana()
    return null;
  }
}
// 2、工厂方法模式:进一步抽象创建类的工厂,这让实例化的对象是可扩展的
interface FruitFactory {
  getFruit(c: string): Fruit
}
class Peach extends Fruit { }
class PeachFactory extends Fruit implements FruitFactory {
  getFruit(c: string): Fruit {
    const peach = new Peach()
    peach.color = c
    return peach
  }
}
const peachFactory = new PeachFactory()
peachFactory.getFruit('pink')
// 3、抽象工厂模式:进一步抽象类的属性,这让实例化的对象的属性也是可扩展的
interface Color {
  colorName(): string
}
class AppleColor implements Color {
  colorName(): string {
    return 'red'
  }
}
abstract class Fruit {
  color: Color
}
class Apple extends Fruit {}
interface FruitFactory {
  getFruit(c: Color): Fruit
}
class AppleFactory extends Fruit implements FruitFactory {
  getFruit(c: Color): Fruit {
    const apple = new Apple()
    apple.color = c
    return apple
  }
}
const appleFactory = new AppleFactory()
appleFactory.getFruit(new AppleColor())

建造者模式(Builder)

也叫生成器模式(Generator),抽象建造者、实际建造者、指挥者、建造产品

应用场景:对象内部组成细节解耦,复杂对象创建过程(比如分阶段、顺序、组合等)

 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
34
35
36
37
// 建造产品
class App {
  name: string
  version: string
}
// 抽象建造者
abstract class Builder {
  app: App = new App()
  abstract requirement(): void
  abstract code(): void
  abstract test(): void
  abstract deploy(): void
  buildApp() {
    return this.app
  }
}
// 实际建造者
class WebBuilder extends Builder {
  requirement() { }
  code() { }
  test() { }
  deploy() {}
}
// 指挥者
class AppDirector {
  appBuilder: Builder
  constructor(builder: Builder) {
    this.appBuilder = builder
  }
  createApp(): App {
    this.appBuilder.requirement();
    this.appBuilder.code()
    this.appBuilder.test()
    this.appBuilder.deploy()
    return this.appBuilder.app
  }
}

结构型模式: 7种

对象的组成及对象之间的依赖关系

适配器模式(Adapter)

让两个没任何关系的类一起运行

应用场景:主要是解决历史遗留问题,被适配者的接口不合规范

 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
34
35
36
37
38
39
40
interface Target { // 目标对象
  fn(): void
}
class Adaptee { // 被适配者
  constructor() { }
  myFn() {}
}
// 1、类适配器:通过继承实现,会暴露被适配对象的方法,Target 必须是接口
class Adapter extends Adaptee implements Target {
  constructor() {
    super()
  }
  fn() {
    super.myFn()
  }
}
new Adapter().fn()
// 2、对象适配器:通过组合实现,Target 可以是类
class Adapter implements Target {
  private adaptee: Adaptee
  constructor(adaptee: Adaptee) {
    this.adaptee = adaptee
  }
  fn() {
    this.adaptee.myFn()
  }
}
new Adapter(new Adaptee()).fn()
// 3、接口适配器:用于不想实现某个接口的全部方法
interface Adaptee {
  fn1(): void
  fn2(): void
}
abstract class AbsAdapter implements Adaptee {
  fn1() { }
  fn2() { }
}
class MyClass extends AbsAdapter {
  fn1() {}
}

装饰器模式(Decorator)

与继承类似,在原来的类上进行扩展

应用场景:原类无法被继承,继承的实现复杂

 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
34
/**
 * 假设有一件衣服,有颜色和设置颜色的方法,设置不同的颜色时应用不同的图案
 * 如果使用继承实现,每新增一种颜色都要修改原类
 * 使用装饰器,只需要新的颜色方案继承这个装饰器就行了
 */
abstract class ICloth {
  setColor(c: string): { };
}
class Cloth implements ICloth {
  color: string;
  setColor(c: string) {
    this.color = c;
  }
}
// 提供装饰器,将 Cloth 托管
abstract class ChangeColorDecorator implements ICloth {
  cloth: ICloth;
  constructor(cloth: ICloth) {
    this.cloth = cloth;
  }
  setColor(c: string): void {
    // 转发给被托管的对象
    this.cloth.setColor(c);
  }
}
class WhiteCloth extends ChangeColorDecorator {
  constructor(cloth: ICloth) {
    super(cloth);
  }
  setColor(): void {
    this.cloth.setColor("white");
    // TODO 白色图案
  }
}

代理模式(Proxy)

全权代理目标对象的所有行为,对目标对象进行隐藏和控制

应用场景:目标对象只执行具体的操作,业务都托管给代理

 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
34
35
36
37
38
39
/**
 * 假设农场主可以种植、采购、销售等
 * 代理复杂告诉农场主,该种什么
 * 通过以下代码发现:静态代理和装饰器模式非常像
 * 不同之处在于:静态代理目标对象所有行为都被托管,装饰器模式只扩展部分
 */
// 1、静态代理:服务对象单一,需要在程序运行前确定被代理对象
interface FarmerWork {
  planting(seed: string): void;
}
class Farmer implements FarmerWork {
  name: string;
  constructor(n: string) {
    this.name = n;
  }
  planting(seed: string): void {
    console.log("I am planting " + seed);
  }
}
class FarmerProxy implements FarmerWork {
  private farmer: Farmer;
  constructor(f: Farmer) {
    this.farmer = f;
  }
  planting(seed: string): void {
    this.farmer.planting(seed);
  }
}
// 2、动态代理:在程序运行时确定被代理对象,JS 提供 Proxy 类代理对象
const proxy = new Proxy(new Farmer("Bob"), {
  get(target, prop, receiver) { // target 内部属性和函数调用都在这里触发
    return Reflect.get(target, prop, receiver);
  },
  apply(target, thisArg, argArray) { // target 是函数,且被调用的时候触发
    console.log("target, thisArg, argArray", target, thisArg, argArray);
  },
});
proxy.name;
proxy.planting("apple");

外观模式(Facade)

屏蔽复杂的底层实现逻辑

应用场景:实力化对象不需要关注内部过程

 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
/**
 * 计算机启动需要按顺序加载硬件,对用户来说只需要按开机就行了
 */
class CPU {
  constructor() {}
  start() {}
}
class Board {
  constructor() {}
  start() {}
}
class Memory {
  constructor() {}
  start() {}
}
class Computer {
  cpu: CPU;
  board: Board;
  memory: Memory;
  constructor() {
    this.cpu = new Board();
    this.board = new Board();
    this.memory = new Memory();
  }
  start() {
    this.board.start(); // 主板通电
    this.cpu.start(); // cpu 就绪
    this.memory.start(); // 内存就绪
  }
}

桥接模式(Bridge)

最复杂的模式之一,将 事务对象具体行为、特征 分离

应用场景:抽象与实现的解耦,让对象和行为特征都能扩展

 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
34
/**
 * 绘制圆形
 */
// 抽象绘制行为
interface AbsDrawCircle {
  drawCircle(x: number, y: number, radius: number): void;
}
// 实现绘制行为
class DrawCircle implements AbsDrawCircle {
  drawCircle(x: number, y: number, radius: number): void {
    console.log(`在[${x},${y}]位置绘制半径为${radius}的圆`);
  }
}
// 抽象形状
interface Shape {
  draw(): void;
}
// 实现形状
class CircleShape implements Shape {
  x: number;
  y: number;
  r: number;
  drawApi: AbsDrawCircle;
  constructor(x: number, y: number, r: number, drawApi: AbsDrawCircle) {
    this.x = x;
    this.y = y;
    this.r = r;
    this.drawApi = drawApi;
  }
  draw(): void {
    this.drawApi.drawCircle(this.x, this.y, this.r);
  }
}
new CircleShape(1, 2, 3, new DrawCircle());

享元模式(Flyweight)

能够共享的部分放在数据结构外部,需要用到时传递给享元

应用场景:程序中使用了大量相似对象,对象的大多数状态可以变为外部的状态

 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
34
35
36
37
38
39
/**
 * 手机对象有以下状态:型号、内存、序列号
 * 其中:型号和内存可以提取到外部共享
 */
class PhoneFlyweight {
  // 手机共享状态
  model: string;
  memory: number;
  constructor(model: string, memory: number) {
    this.model = model;
    this.memory = memory;
  }
}
class PhoneFlyweightFactory {
  // 共享状态创建工厂
  private map: Record<string, PhoneFlyweight> = {};
  get(model: string, memory: number): PhoneFlyweight {
    // 没有则创建,有直接返回
    const key = model + memory;
    if (!this.map[key]) this.map[key] = new PhoneFlyweight(model, memory);
    return this.map[key];
  }
}
class Phone {
  flyweight: PhoneFlyweight;
  sn: string;
  constructor(fly: PhoneFlyweight, sn: string) {
    this.flyweight = fly;
    this.sn = sn;
  }
}
class PhoneFactory {
  static flyFactory: PhoneFlyweightFactory = new PhoneFlyweightFactory();
  getPhone(model: string, memory: number, sn: string) {
    const fly = PhoneFactory.flyFactory.get(model, memory);
    return new Phone(fly, sn);
  }
}
// 生产 10000 台手机,型号和内存都共用有限的几种组合

组合模式(Composite)

将同一抽象或接口实例放入同一树状结构

应用场景:局部与整体结构相同,层次树形结构

1
2
3
4
5
6
7
8
abstract class Component {
  // TODO 一些属性、增删方法等
}
class Leaf extends Component {}
class Composite extends Component {
  children: Composite[] = [];
}
const Tree = new Composite();

行为型模式: 11种

对象方法及调用直接的关系

策略模式(Strategy)

抽象方法作为一个策略、不同的类各自实现这个策略

应用场景:对象的某个行为在不同的场景下实现方式不同

 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
/**
 * 中西餐的吃饭方式
 */
interface EatStrategy {
  eat(): void;
}
class ChineseStrategy implements EatStrategy {
  eat(): void {
    console.log("使用筷子");
  }
}
class WesternStrategy implements EatStrategy {
  eat(): void {
    console.log("使用刀叉");
  }
}
// 决策者
class Decision {
  eatStrategy: EatStrategy;
  constructor(s: EatStrategy) {
    this.eatStrategy = s;
  }
  eat() {
    this.eatStrategy.eat();
  }
}
new Decision(new ChineseStrategy()).eat(); // 使用筷子
new Decision(new WesternStrategy()).eat(); // 使用刀叉

模板方法模式

父类定义执行顺序,执行单元可以不被实现,流程方法不能被重写。子类负责实现执行单元

应用场景:控制反转,固定流程顺序

 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
/**
 * 联机竞赛游戏示例
 */
abstract class Game {
  protected palyerCount: number;
  abstract initializeGame(): void;
  abstract makePlay(count: number): void;
  abstract endOfGame(): boolean;
  abstract printWinner(): void;
  // 流程不可被重载
  start(count: number) {
    this.palyerCount = count;
    this.initializeGame();
    while (!this.endOfGame()) {
      this.makePlay(this.palyerCount--);
    }
    this.printWinner();
  }
}
class Chess extends Game {
  initializeGame(): void {}
  makePlay(count: number): void {}
  endOfGame(): boolean {
    return this.palyerCount > 0;
  }
  printWinner(): void {}
}
new Chess().start(10);

观察者模式(Observer)

目标对象依赖于它的观察者对象,自身状态改变时发出通知

应用场景:即时事件处理

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 观察者
interface Watcher {
  update(): void;
}
// 订阅者
interface Subscriber {
  addWatcher(watcher: Watcher): void;
  removeWatcher(watcher: Watcher): void;
  notifyWatcher(): void;
}
// 被观察对象
class Target implements Subscriber {
  watchers: Watcher[] = [];
  addWatcher(watcher: Watcher): void {
    this.watchers.push(watcher);
  }
  removeWatcher(watcher: Watcher): void {
    this.watchers = this.watchers.filter((w) => watcher !== w);
  }
  notifyWatcher(): void {
    this.watchers.forEach((w) => w.update());
  }
}

迭代器模式(Iterator)

实现一种遍历方式

应用场景:内部实现无关的集合的迭代

责任链模式

有责任对象则传递事件,没有则处理

应用场景:事件的分层处理及流程传递

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
// 抽象责任链对象
abstract class Widget {
  protected nextWidget: Widget;
  deal() {}
  getNextWidget() {
    return this.nextWidget;
  }
  setNextWidget(w: Widget) {
    this.nextWidget = w;
  }
}
// 实现事件传递
class Role extends Widget {
  deal(): void {
    if (this.getNextWidget()) this.getNextWidget().deal();
    else this.deal();
  }
}

命令模式

命令者和被命令者的分离

应用场景:一个命令可以被任意被命令者接收

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
interface Command {
  exe(): void;
}
class Receiver {
  action() {}
}
class Commander implements Command {
  receiver: Receiver;
  constructor(rc: Receiver) {
    this.receiver = rc;
  }
  exe(): void {
    this.receiver.action();
  }
}

备忘录模式

记住之前操作的节点,在某些时候回到某个节点

应用场景:快照,撤销操作

 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 Memento {
  private _state: number;
  constructor(shot: Snapshot) {
    this._state = shot.state;
  }
  get state() {
    return this._state;
  }
}
// 快照:set 和 get 可以让实例直接通过方法名取值赋值
class Snapshot {
  private _state: number;
  get state() {
    return this._state;
  }
  set state(st: number) {
    this._state = st;
  }
  createMemento() {
    // 创建备忘录
    return new Memento(this);
  }
  restoreMemento(m: Memento) {
    // 撤销
    this._state = m.state;
  }
}
const snapshot = new Snapshot();
snapshot.state = 3;
const memento = snapshot.createMemento();
snapshot.state = 4;
snapshot.restoreMemento(memento);

状态模式

方法实现因状态的不同而不同

应用场景:状态的差异比较大

 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
/**
 * 水的两种状态,用处不一样
 */
interface IWaterState {
  use(): void;
}
class IceState implements IWaterState {
  use(): void {
    console.log("固态,用于冷藏");
  }
}
class WaterState implements IWaterState {
  use(): void {
    console.log("液态,用于清洗");
  }
}
class Context implements IWaterState {
  private state: IWaterState;
  setState(s: IWaterState) {
    this.state = s;
    return this;
  }
  use(): void {
    this.state.use();
  }
}
const context = new Context();
context.setState(new IceState()).use();
context.setState(new WaterState()).use();

访问者模式

算法与对象结构分离

应用场景:对象不同的访问者有不同的操作

 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
34
35
36
// 抽象访问者
interface Visitor {
  visit(o: Wheel | Engine): void;
}
// 被访问者
class Wheel {
  private _name: string;
  constructor(name: string) {
    this._name = name;
  }
  get name() {
    return this._name;
  }
  accept(visitor: Visitor) {
    visitor.visit(this);
  }
}
class Engine {
  accept(visitor: Visitor) {
    visitor.visit(this);
  }
}
// 实现访问者
class TodoVisitor implements Visitor {
  visit(o: Wheel | Engine): void {
    if (o instanceof Wheel) {
      console.log(o.name);
    }
    if (o instanceof Engine) {
      console.log("engine");
    }
  }
}
const visitor = new TodoVisitor();
new Wheel("F4").accept(visitor); // F4
new Engine().accept(visitor); // engine

中介者模式

所有对象不互相通信,而是通过中介者,所有的通信过程封装在中介者中

应用场景:复杂的对象通信、通信解耦

 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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
// 抽象通信过程
interface Command {
  execute(): void;
}
// 两个需要通信的类
class View implements Command {
  private _loading: boolean;
  private mediator: Mediator
  constructor(med: Mediator) {
    this.mediator = med;
    this.mediator.registerView(this)
  }
  execute(): void {
    this.mediator.view()
  }
  get loading() {
    return this._loading
  }
  set loading(flag: boolean) {
    this._loading = flag
  }
}
class Search implements Command {
  private _loading: boolean;
  private mediator: Mediator
  constructor(med: Mediator) {
    this.mediator = med;
    this.mediator.registerSearch(this)
  }
  execute(): void {
    this.mediator.search()
  }
  get loading() {
    return this._loading
  }
  set loading(flag: boolean) {
    this._loading = flag
  }
}
// 抽象中介
interface Mediator {
  search(): void;
  view(): void;
  registerView(v: View): void;
  registerSearch(s: Search): void;
}
// 实现中介
class RealMediator implements Mediator {
  private viewObj: View;
  private searchObj: Search;
  search(): void {
    this.viewObj.loading = false;
    this.searchObj.loading = true
  }
  view(): void {
    this.viewObj.loading = true;
    this.searchObj.loading = false
  }
  registerView(v: View): void {
    this.viewObj = v
  }
  registerSearch(s: Search): void {
    this.searchObj = s
  }
}
const med = new RealMediator()
new View(med).execute()
new Search(med).execute()

解释器模式

抽象表达式,终结符表达式,非终结符表达式

应用场景:文法解释器、语法分析、词法分析

一般用于编程语言设计,使用场景不多,实现较为复杂这里就不贴代码了,感兴趣的可自行搜索