面向对象设计模式
面向对象编程范式中,我所了解的,设计模式一共有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()
|
解释器模式
抽象表达式,终结符表达式,非终结符表达式
应用场景:文法解释器、语法分析、词法分析
一般用于编程语言设计,使用场景不多,实现较为复杂这里就不贴代码了,感兴趣的可自行搜索