跳到主要内容

设计模式概念

Design pattern is a proved methodology & solution to a problem in a context of some software system/application. (已证实的方法或解法)

More specifically, play a role of a standard solution to a recurring problem (重现问题的标准解法)

Pattern is the knowledge of reuse of generated knowledge

创建型 Creational,结构型 Structuaral ,行为型 Behavioral

  • 创建型: 用于创建一个对象
  • 结构型: 用于将多个对象组
  • 织到高效的一个当中
  • 行为型: 用于描述不同类和对象之间互相互动和分配职责

类式 对象式

  • 类式用于管理类和子类的关系
  • 对象式用于管理对象的关系

设计模式原则​

单一职责原则(Single Responsibility Principle)​

SRP

每个函数(类)只做一件事情, 同时职责完全被该函数(类)管理

  • 如果功能比较复杂,可以拆成多个函数,同时让每个部分保持独立
  • 好处:修改一个功能时,不会影响到其他功能

开闭原则(OpenClosed Principle)​

OCP 对扩展开放,对修改关闭

  • 在实现新功能时,扩展新代码,而不是修改已有代码
  • 好处:不会影响已有功能

里式代换原则(Liskov Substitution Principle)​

Function that use pointers or references to base classes must be able to use objects of derived classes without knowing it

LSP 所有引用基类的地方必须能透明地使用其子类的对象

依赖倒转原则(Dependence Inversion Principle)​

Program to an interface, not an implementation

DIP

高层模块不应该依赖低层模块,他们都应该依赖抽象。抽象不应该依赖细节,细节应该依赖于抽象

接口隔离原则 (Interface Segregation Principle)​

ISP

用户不应该被强制依赖他们不使用的接口,即只给用户必须使用的(less is more)

合成复用原则(Composite Reuse Principle)​

CRP

Favor composition of object over inheritance as a reuse mechanism

迪米特法则 (Law of Demeter)​

Lod

任何软件单元应该只对其他单元保持限制的知识

结构型​

代理模式​

为对象提供代理,以控制对它的访问 真实工厂负责生产商品,代理工厂负责生产商品之外的事情,从而可以让真实工厂专注于生产

其他例子:Proxy

// 真实工厂
class Factory {
constructor(count) {
// 工厂默认有1000件产品
this.productions = count || 1000;
}

// 生产商品
produce(count) {
// 原则上低于5个工厂是不接单的
this.productions += count;
}

// 向外批发
wholesale(count) {
// 原则上低于10个工厂是不批发的
this.productions -= count;
}
}

// 代理工厂
class ProxyFactory extends Factory {
// 代理工厂默认第一次合作就从工厂拿100件库存
constructor(count = 100) {
super(count);
}

// 代理工厂向真实工厂下订单之前会做一些过滤
produce(count) {
if (count > 5) {
super.produce(count);
} else {
console.log("低于5件不接单");
}
}

wholesale(count) {
if (count > 10) {
super.wholesale(count);
} else {
console.log("低于10件不批发");
}
}

taobao(count) {
// ...
}

logistics() {
// ...
}
}

// 创建一个代理工厂
const proxyFactory = new ProxyFactory();

// 通过代理工厂生产4件商品,被拒绝
proxyFactory.produce(4);

// 通过代理工厂批发20件商品
proxyFactory.wholesale(20);

// 代理工厂的剩余商品 80
console.log(proxyFactory.productions);

组合模式​

用树形结构来表示一组对象 对单个对象和组合对象的处理逻辑进行统一 扫描文件夹时,文件夹里可能是文件,也可能是文件夹,不对它们进行区别对待

const Folder = function (folder) {
this.folder = folder;
this.lists = [];
};

Folder.prototype.add = function (resource) {
this.lists.push(resource);
};

Folder.prototype.scan = function () {
console.log("开始扫描文件夹: ", this.folder);
for (let i = 0, folder; (folder = this.lists[i++]); ) {
folder.scan();
}
};

const File = function (file) {
this.file = file;
};

File.prototype.add = function () {
throw Error("文件下不能添加其它文件夹或文件");
};

File.prototype.scan = function () {
console.log("开始扫描文件: ", this.file);
};

const folder = new Folder("根文件夹");
const folder1 = new Folder("JS");
const folder2 = new Folder("life");

const file1 = new File("深入React技术栈.pdf");
const file2 = new File("JavaScript权威指南.pdf");
const file3 = new File("小王子.pdf");

folder1.add(file1);
folder1.add(file2);

folder2.add(file3);

folder.add(folder1);
folder.add(folder2);

folder.scan();

// 开始扫描文件夹: 根文件夹
// 开始扫描文件夹: JS
// 开始扫描文件: 深入React技术栈.pdf
// 开始扫描文件: JavaScript权威指南.pdf
// 开始扫描文件夹: life
// 开始扫描文件: 小王子.pdf