设计1

26 阅读3分钟

学习设计模式,有助于写出可复用和可维护性高的程序

设计模式是找出程序中变化的地方,并将变化封装起来,它的关键是这种封装的意图,而不是固定需要某种代码结构来实现。

设计模式需要遵循三个基本原则

总体原则

单一职责原则(SRP)

一个对象或方法只做一件事情。如果一个方法承担了过多的职责,那么在需求的变迁过程中,需要改写这个方法的可能性就越大。

应该把对象或方法划分成较小的粒度

最少知识原则(LKP)

一个软件实体应当 尽可能少地与其他实体发生相互作用 

应当尽量减少对象之间的交互。如果两个对象之间不必彼此直接通信,那么这两个对象就不要发生直接的 相互联系,可以转交给第三方进行处理

开放-封闭原则(OCP)

软件实体(类、模块、函数)等应该是可以 扩展的,但是不可修改

当需要改变一个程序的功能或者给这个程序增加新功能的时候,可以使用增加代码的方式,尽量避免改动程序的源代码,防止影响原系统的稳定

每个设计模式,我们围绕它的基本定义,以及本质的特点,还有一个示例的实现,以及简单说一下它们有没有什么优缺点,适用的地方等几个角度去分析说明一些

一、单例模式

1. 定义

保证一个类仅有一个实例,并提供一个访问它的全局访问点

2. 核心

确保只有一个实例,并提供全局访问

3. 实现

假设要设置一个管理员,多次调用也仅设置一次,我们可以使用闭包缓存一个内部变量来实现这个单例

js
 体验AI代码助手
 代码解读
复制代码
function SetManager(name) {
    this.manager = name;
}

SetManager.prototype.getName = function() {
    console.log(this.manager);
};

var SingletonSetManager = (function() {
    var manager = null;

    return function(name) {
        if (!manager) {
            manager = new SetManager(name);
        }

        return manager;
    } 
})();

SingletonSetManager('a').getName(); // a
SingletonSetManager('b').getName(); // a
SingletonSetManager('c').getName(); // a

这是比较简单的做法,但是假如我们还要设置一个HR呢?就得复制一遍代码了

所以,可以改写单例内部,实现地更通用一些

js
 体验AI代码助手
 代码解读
复制代码
// 提取出通用的单例
function getSingleton(fn) {
    var instance = null;

    return function() {
        if (!instance) {
            instance = fn.apply(this, arguments);
        }

        return instance;
    }
}

再进行调用,结果还是一样

js
 体验AI代码助手
 代码解读
复制代码
// 获取单例
var managerSingleton = getSingleton(function(name) {
    var manager = new SetManager(name);
    return manager;
});

managerSingleton('a').getName(); // a
managerSingleton('b').getName(); // a
managerSingleton('c').getName(); // a

这时,我们添加HR时,就不需要更改获取单例内部的实现了,仅需要实现添加HR所需要做的,再调用即可

js
 体验AI代码助手
 代码解读
复制代码
function SetHr(name) {
    this.hr = name;
}

SetHr.prototype.getName = function() {
    console.log(this.hr);
};

var hrSingleton = getSingleton(function(name) {
    var hr = new SetHr(name);
    return hr;
});

hrSingleton('aa').getName(); // aa
hrSingleton('bb').getName(); // aa
hrSingleton('cc').getName(); // aa

或者,仅想要创建一个div层,不需要将对象实例化,直接调用函数

结果为页面中仅有第一个创建的div

js
 体验AI代码助手
 代码解读
复制代码
function createPopup(html) {
    var div = document.createElement('div');
    div.innerHTML = html;
    document.body.append(div);

    return div;
}

var popupSingleton = getSingleton(function() {
    var div = createPopup.apply(this, arguments);
    return div;
});

console.log(
    popupSingleton('aaa').innerHTML,
    popupSingleton('bbb').innerHTML,
    popupSingleton('bbb').innerHTML
); // aaa  aaa  aaa