设计原则
单一职责原则- SRP
开放封闭原则 - OCP
里氏替换原则 - LSP
接口隔离原则 - ISP
依赖倒转原则 - DIP
迪米特法则 - DP
合成复用原则 - CSP
什么时候去解耦
如果两个职责在修改的时候,都是同时变化,就不必解耦开;
如果未来可能会独立复用,可以考虑单一职责。
单一职责原则- SRP
js
class UserOptions {
//修改用户的名称、修改用户的密码
updateUserInfo(user, type) {
if (type === "username") {
this.user.username = user.username;
} else if (type === "password") {
this.user.password = user.password;
}
}
}
const userOpts = new UserOptions();
userOpts.updateUserInfo({ username: '张三' }, "username");
class UserOptionsSRP {
updateUserName(username) {
this.user.username = username;
}
updatePassword(password) {
this.user.password = password;
}
}
开放封闭原则 - OCP基础

里氏替换原则 - LSP
在设计的子类的时候,可以完整地继承父类的职责,而不是去修改。
组合的方式,可能会优于继承;
多考虑多态逻辑的实现和应用。
接口隔离原则 - ISP
接口隔离原则
意义和目的是,尽量减少接口之间的耦合存在,在大型的软件架构设计中,多个接口的组合使用,好过一个大而全的接口。
1接口尽量小;
2接口要高内聚
依赖倒转原则 - DIP
依赖倒转原则的核心,是减少高层模块和底层模块之间的耦合。
高层模块不应该直接依赖底层模块,两者都应该依赖于抽象
抽象不应该依赖于细节,细节应该依赖于抽象。
设计模式
创建型:工厂、单例、建造者
结构型:装饰器模式、适配器模式、代理模式
行为型:观察者模式、发布订阅模式、策略模式
构造器模式
js
function Employee(name, age) {
this.name = name;
this.age = age;
this.say = function () {
console.log(`我的名字是${this.name},今年${this.age}岁`);
};
}
var employee1 = new Employee("小王", 100);
var employee2 = new Employee("tiechui", 18);
console.log(employee1, employee2);
employee1.say();
employee2.say();
原型模式
js
function Employee(name, age) {
this.name = name;
this.age = age;
}
Employee.prototype.say = function () {
console.log(`我的名字是${this.name},今年${this.age}岁`);
};
var employee1 = new Employee("小王", 100);
var employee2 = new Employee("tiechui", 18);
console.log(employee1, employee2);
employee1.say();
employee2.say();
js
class Employee {
constructor(name, age) {
this.name = name;
this.age = age;
}
say() {
console.log(`我的名字是${this.name},今年${this.age}岁`);
}
}
var employee1 = new Employee("小王", 100);
var employee2 = new Employee("tiechui", 18);
console.log(employee1, employee2);
employee1.say();
employee2.say();
建造者模式
js
function Car() {
};
Car.prototype.init = function (
door,
options,
color,
bland
) {
this.initDoor(door)
.initOptions(options)
.initColor(color)
.initBland(bland)
}
Car.prototype.initDoor = function (door) {
this.door = door;
return this;
}
Car.prototype.initOptions = function (options) {
this.options = options;
return this;
}
Car.prototype.initColor = function (color) {
this.color = color;
return this;
}
Car.prototype.initBland = function (bland) {
this.bland = bland;
return this;
}
const MyCar = new Car();
MyCar.initDoor(4)
.initOptions(['ABS', 'GPS'])
.initColor('white')
.initBland('Benz');
console.log(MyCar);
工厂模式
当满足以下任一条件时,即可考虑使用:
对象创建步骤多、逻辑复杂;
需根据条件动态选择创建的对象类型;
希望统一管理对象的生命周期(如复用、监控);
需降低代码对具体类的依赖,便于后续扩展或替换
简单工厂
es5
js
function UserFactory(role) {
function User(role, pages) {
this.role = role;
this.pages = pages;
}
switch (role) {
case 'superadmin':
return new User('superadmin', ['home', 'user-manage', 'right-manage', 'news-manage']);
case 'admin':
return new User('admin', ['home', 'user-manage', 'news-manage']);
case 'editor':
return new User('editor', ['home', 'news-manage']);
default:
throw new Error('参数错误');
}
}
var user = UserFactory('superadmin');
console.log(user);
es6
js
class User {
constructor(role, pages) {
this.role = role;
this.pages = pages;
}
static UserFactory(role) {
switch (role) {
case 'superadmin':
return new User('superadmin', ['home', 'user-manage', 'right-manage', 'news-manage']);
case 'admin':
return new User('admin', ['home', 'user-manage', 'news-manage']);
case 'editor':
return new User('editor', ['home', 'news-manage']);
default:
throw new Error('参数错误');
}
}
}
var user = User.UserFactory('superadmin');
console.log(user);
抽象工厂
假如对于实际的生产来说,我的BYD和dongfeng不可能是一个工厂生产
js
class AbstratFacrtory {
createCar() {};
createTruck() {};
};
class Car {
constructor() {
this.door = 4;
this.options = ['drive', 'drived'];
}
};
class Truck {
constructor() {
this.door = 2;
this.options = ['drive', 'pullGoods'];
}
};
class DongfengCar extends Car {
constructor(color) {
super();
this.bland = 'dongfeng';
this.color = color;
}
}
class BYDCar extends Car {
constructor(color) {
super();
this.bland = 'byd';
this.color = color;
}
}
class DongfengTruck extends Truck {
constructor() {
super();
this.bland = 'dongfeng';
}
}
class BYDTruck extends Truck {
constructor() {
super();
this.bland = 'byd';
}
}
class DongfengFactory {
createCar(color) {
return new DongfengCar(color);
}
createTruck() {
return new Truck();
}
}
class BYDFactory {
createCar(color) {
return new BYDCar(color);
}
createTruck() {
return new BYDTruck();
}
}
const myFactory = new BYDFactory();
const myCar = myFactory.createCar('blue');
console.log(myCar);
js
class User {
constructor(name, role, pages) {
this.name = name;
this.role = role;
this.pages = pages;
}
welcome() {
console.log(`欢迎回来`, this.name);
}
dataShow() {
throw new Error('抽象方法需要被实现');
}
}
class SuperAdmin extends User {
constructor(name) {
super(name, 'superadmin', ['home', 'user-manage', 'right-manage', 'news-manage']);
}
dataShow() {
console.log(`superadmin-datashow`);
}
addRight() {
}
addUser() {
}
}
class Admin extends User {
constructor(name) {
super(name, 'admin', ['home', 'user-manage', 'news-manage']);
}
dataShow() {
console.log(`superadmin-datashow`);
}
addRight() {
}
addUser() {
}
}
class Editor extends User {
constructor(name) {
super(name, 'editor', ['home', 'news-manage', 'new-manage']);
}
dataShow() {
console.log(`superadmin-datashow`);
}
addRight() {
}
addUser() {
}
}
function getAbstratctUserFactory(role) {
switch (role) {
case 'superadmin':
return new SuperAdmin('superadmin');
case 'admin':
return new Admin('admin');
case 'editor':
return new Editor('editor');
default:
throw new Error('参数错误');
}
}
let user = getAbstratctUserFactory('superadmin');
console.log(user);
单例模式
是全局的,唯一的实例
好处
全局唯一
可以实现状态状态管理
坏处
副作用太大
不符合单一职责的原则。
Vue项目中的Vue实例
Node项目中的App实例
Vuex React-Redux中的store
js
// ###########################################################构造函数的实现,实例在外部
let singleton;
function Singleton() {
if (!singleton) {
singleton = this;
}
return singleton;
}
Singleton.prototype.getName = function () {
console.log('我是单例');
}
let singleton1 = new Singleton();
let singleton2 = new Singleton();
console.log(singleton1 === singleton2);
// ###########################################################实例在内部
function Singleton2() {
this.instance = null;
}
Singleton2.getInstance = function () {
if (!this.instance) {
this.instance = new Singleton2();
}
}
Singleton2.prototype.getName = function () {
console.log('我是单例');
}
const single2A = Singleton2.getInstance();
const single2B = Singleton2.getInstance();
console.log(single2A === single2B);
// #####################################################################使用闭包
const Singleton3 = (function () {
let instance;
function createInstance() {
instance = '单例';
return instance;
}
return {
getInstance: function () {
if (!instance) {
instance = createInstance();
}
return instance;
}
}
})();
const ins1 = Singleton3.getInstance();
const ins2 = Singleton3.getInstance();
console.log(ins1 === ins2);
es6
js
class Singleton {
static instance;
constructor() {
if (!Singleton.instance) {
Singleton.instance = this;
}
return Singleton.instance;
}
}
const instance1 = new Singleton();
const instance2 = new Singleton();
console.log(instance1 === instance2);
代理模式
VUE
object.defineProperty
new Proxy();
数据缓存的代理
localStorage的缓存 -- localStorage优先使用

观察者模式

js
class Subject {
constructor() {
this.deps = [];
// state发生改变时,通知所有的observer
this.state = 0;
}
attach(observer) {
this.deps.push(observer);
}
setState(num) {
this.state = num;
this.notifyAllObservers();
}
notifyAllObservers() {
this.deps.forEach(obs => obs.run(this.state))
}
}
class Observer {
constructor(subject) {
this.subject = subject;
this.subject.attach(this);
}
run() {
}
}
class BinaryObserver extends Observer {
constructor(subject) {
super(subject);
}
run(data) {
console.log(`hello, this is binaryObserver: ${data}`);
}
}
class ArrayObserver extends Observer {
constructor(subject) {
super(subject);
}
run(data) {
console.log(`hello, this is arrayObserver: ${data}`);
}
}
const subject = new Subject();
const bobs = new BinaryObserver(subject);
const aobs = new ArrayObserver(subject);
subject.setState(15);
js
class Subject {
constructor() {
this.observers = [];
}
add(observer) {
this.observers.push(observer);
}
remove(observer) {
const index = this.observers.indexOf(observer);
if (index !== -1) {
this.observers.splice(index, 1);
}
}
notify(data) {
this.observers.forEach(obs => obs.update(data));
}
}
class Observer {
constructor(name) {
this.name = name;
}
update(data) {
console.log(`${this.name} 收到数据:${data}`);
}
}
const subject = new Subject();
const observer1 = new Observer('张三');
const observer2 = new Observer('李四');
subject.add(observer1);
subject.add(observer2);
setTimeout(() => {
subject.remove(observer1)
}, 1000);
setTimeout(() => {
subject.notify('Hello World!');
}, 1000);
发布订阅者模式
解耦代码
装饰器模式
保证原有函数功能不变的同时,增加一个新的功能(AOP面向切面编程)
ES和TypeScript的Decoratori语法
类装饰器,函数(方法)装饰器,属性装饰器
实现方式:class、高阶函数

适配器模式
js
class Target {
api() {
console.log('this is the api');
}
}
class Adaptee {
newLogic() {
console.log('new logic');
}
}
class Adaptor extends Target {
constructor(adaptee) {
super();
this.adaptee = adaptee;
}
api() {
this.adaptee.newLogic();
}
}
const adaptor = new Adaptor(new Adaptee());
adaptor.api();
js
class TencentMap {
show() {
console.log('开始渲染腾讯地图');
}
}
class BaiduMap {
display() {
console.log('开始渲染百度地图');
}
}
class TencentAdapater extends TencentMap {
constructor() {
super();
}
display() {
this.show();
}
}
function renderMap(map) {
map.display();
}
renderMap(new TencentAdapater());
renderMap(new BaiduMap());
策略模式
js
let strategry = {
A: function (salary) {
return salary * 4;
},
B: function (salary) {
return salary * 3;
},
C: function (salary) {
return salary * 2;
}
}
function calBonus(level, salary) {
return strategry[level](salary);
}
console.log(calBonus('A', 2000));
模块模式

桥接模式
桥接模式:将抽象部分与它的实现部分分离,使它们都可以独立地变化。
使用场景:一个类存在两个或多个独立变化的维度,且这两个维度都需要进行扩展
优点:
把抽象与实现隔离开,有助于独立地管理各组成部分。
缺点:
每使用一个桥接元素都要增加一次函数调用,这对应用程序的性能会有一些负面影响一一提高了系统的复杂程度。
组合模式
命令模式
宏命令
js
class MacroCommand {
constructor() {
this.list = [] //子命令对象
}
add(command) {
this.list.push(command)
}
execute() {
for (let item of this.list) {
item.execute()
}
}
}
const Tabs = {
execute(){
console.log('选项卡执行');
}
}
const Swipe = {
execute(){
console.log('轮播执行');
}
}
const macroCommand = new MacroCommand()
macroCommand.add(Tabs)
macroCommand.add(Swipe)
macroCommand.execute()
模版方法模式
js
var Container = function (params = {}) {
var F = function () { };
F.prototype.init = function () {
this.getData();
this.render();
}
F.prototype.getData = params.getData || function () {
throw new Error('必须传入getData方法')
}
F.prototype.render = function () {
console.log('render');
}
return F;
};
var Myclass = Container({
getData() {
console.log('获取comingsoon');
return [4, 5, 6]
}
});
new Myclass().init();
迭代器模式
迭代器模式是指提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部表示。迭
代器模式可以把选代的过程从业务逻辑中分离出来,在使用迭代器模式之后,即使不关心对象的内部构造,
也可以按顺序访问其中的每个元素。
1.为遍历不同数据结构的"集合"提供统一的接口;
2.能遍历访问"集合"数据中的项,不关心项的数据结构
js
var obj = {
codeL: 200,
name: 'kerwin',
list: ['aaaa', 'bbbb', 'ccc'],
[Symbol.iterator]: function () {
var index = 0;
return {
next: () => {
if (index < this.list.length) {
return {
value: this.list[index++],
done: false
}
} else {
return {
value: undefined,
done: true
}
}
}
}
}
}
for (let item of obj) {
console.log(item)
}
职责链模式
使多个对象都有机会处理请求,从而避免了请求的发送者与多个接收者直接的耦合关系,将这些接收者连接
成一条链,顺着这条链传递该请求,直到找到能处理该请求的对象。
优点:
1.符合单一职责,使每个方法中都只有一个职责。
2.符合开放封闭原则,在需求增加时可以很方便的扩充新的责任
3.使用时候不需要知道谁才是真正处理方法,减少大量的if或switch语法。
缺点:
1.团队成员需要对责任链存在共识,否则当看到一个方法莫名其妙的返回一个nxt时一定会很奇怪。
2.出错时不好排查问题,因为不知道到底在哪个责任中出的错,需要从链头开始往后找
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<input type="text" id="input" />
<button id="btn">注册</button>
<script>
btn.onclick = function () {
checks.check();
};
function checkEmpty() {
if (input.value.length === 0) {
console.log("这里不能为空");
return;
}
return "next";
}
function checkNumber() {
if (Number.isNaN(+input.value)) {
console.log("这里只能是数字");
return;
}
return "next";
}
function checkLength() {
if (input.value.length < 6) {
console.log("长度不能小于6");
return;
}
return "next";
}
class Chain {
constructor(fn) {
this.checkRule = fn;
this.nextRule = null;
}
addRule(nextRule) {
this.nextRule = new Chain(nextRule);
return this.nextRule;
}
end() {
this.nextRule = {
check: () => "end"
};
}
check() {
this.checkRule() === "next" ? this.nextRule.check() : null;
}
}
const checks = new Chain(checkEmpty);
checks.addRule(checkNumber).addRule(checkLength).end();
</script>
</body>
</html>