设计原则
· 单一职责原则
· 开放-封闭原则
软件实体可以扩展但不可修改
· 最少知识原则
一个软件实体应当尽可能少的与其他实体发生相互作用
一、单例模式
function Single(name){
this.name = name;
}
Single.prototype.getName = function(){
console.log(this.name);
}
function singleInstance(){
let instance = null;
return function(){
if(!instance) {
instance = new Single('贾贵')
}
return instance;
}
}
二、策略模式
策略模式主要解决的是if-else 逻辑复杂而不可维护的情况
如下代码,模拟一个公司发年终奖的情况
const strategy = {
s(base) {
return base * 5;
},
a(base) {
return base * 4;
},
b(base) {
return base * 3;
},
c(base) {
return base * 2;
},
d(base) {
return base * 1;
},
}
const getBouns = (base, grade) => strategy[base][grade];
const res1 = getBouns(1000, 5) // 5000
三、装饰器模式
在不改变自身的情况下,增加新的功能
如下代码,创建3个plane
plane1 可以发射子弹
plane2 可以发射子弹和火箭弹
plane3 可以发射子弹、火箭弹、导弹。
function Plane1(){
}
Plane1.prototype.fire = function () {
console.log('子弹')
}
function Plane2 (plane) {
this.plane = plane;
}
Plane2.prototype.fire = function () {
this.plane.fire();
console.log('火箭弹');
}
function Plane3 (plane) {
this.plane = plane;
}
Plane3.prototype.fire = function () {
this.plane.fire();
console.log('导弹')
}
let p1 = new Plane1();
let p2 = new Plane2(p1);
let p3 = new Plane3(p2);
四、订阅-发布者模式
js中的事件就是经典的订阅发布者模式
class Observer {
constructor(){
this.follows = [];
}
follow(obj){
this.follow.push(obj)
}
publish(){
this.follows.forEach(item => {
item.fn(item.name);
})
}
}
五、观察者模式
// 定义主题,接受状态变化,并通知每一个观察者
class Sub{
constructor(){
this.state = 0;
this.observers = [];
}
// 获取状态
getState(){
return this.state;
}
// 设置状态
setState(state){
this.state = state;
this.notify();
}
// 新增观察者
addObserver(observer){
this.observers.push(observer);
}
// 通知
notify(){
this.observers.forEach((item) => {
item.update();
})
}
}
// 定义一个观察者
class Obserer {
constructor(name, sub) {
this.name = name;
this.sub = sub;
this.sub.addObserver(this);
}
update(){
console.log('更新了')
}
}
let s = new Sub();
let o = new Observer('李三', s);
o.setState(2);
** 观察者模式和订阅发布者模式的区别:
本质上的区别是调度的地方不同
观察者模式是由具体目标调度的,而发布/订阅模式是统一由调度中心调的,
所以观察者模式的订阅者与发布者之间是存在依赖的,而发布/订阅模式则不会。
**
六、迭代器模式
遍历可迭代对象,就是一种迭代器模式
如下代码,编写了一个倒叙遍历数组的函数
const ary = [1,2,3,4,5,6];
function reverseEcach (ary, callback) {
if(ary.length === 0 ) return ;
for(let index = ary.length - 1; index >= 0 ; index--) {
callback(ary[index], index, ary);
}
}
七、代理模式
主要用于转发请求
如下代码模拟,发送邮件的过程。
但是发送者不直接将邮件发送给接收者。而是通过将邮件交给邮递员,邮递员再将邮件发给接收者。
// 创建邮件对象
function Email(sender, content){
this.sender = sender;
this.content = content;
}
// 发布者
const sender = {
// target : 实际交给谁
// receiver:最终的接收者
// email:邮件
send(target, receiver, email)
}
// 邮递员
const postMan = {
send(receiver, email){
receiver.receive(email)
};
}
// 实际接收者
const receiver = {
receive(email) {
console.log('收到邮件')
}
}
const email = new Email('Tom', 'hello world');
sender.send(postMan, receiver, email);