前端常见设计模式

87 阅读2分钟

单例模式

又称为单体模式。保证一个类只有一个实例,并提供一个访问它的全局访问点。

第二次使用同一个类创建新对象的时候,应该得到第一次创建的对象完全相同的对象。

通过静态属性创建单例

class Person{
    static instance = null; //静态属性,不会被实例继承,由类直接调用
    constructor(name){
        if(Person.instance){
            return Person.instance;
        }
        Person.instance = this;
        this.name = name;
    }
}

通过函数创建单例

let instance;
function createInstance(...arg){
    if(!instance){
        instance = new Game(...arg);
    }
    return instance;
}

==优点:==实现代码复用性,封装良好,抽象逻辑

==缺点:==单例模式扩展性不强

工厂模式

function createPerson(name, age) {
    var obj = {};
    obj.name = name;
    obj.age = age;
    obj.writeJs = function () {
        console.log(this.name + 'write js');
    }
    return obj;
}

var p1 = createPerson('mengzhe' , 26);
p1.writeJs();

var p2 = createPerson('iceman' , 25);
p2.writeJs();

==优点:==实现代码复用性,封装良好,抽象逻辑

==缺点:==不能识别对象的类型,全部是Object

构造函数模式

function Person(name, age, job){
    this.name = name;
    this.age = age;
    this.job = job;
    this.sayName = function(){
       alert(this.name);
    };
}
const scater = new Person("scater", 29, "web前端");
console.log(scater instanceof Person)// true
  • 首字母大写
  • 使用new创建对象

==优点:==能够识别对象

==缺点:==每次创建实例的时候都要重新创建一次方法

原型模式

原型模式适合在创建复杂对象时,对于那些需要一直在变化而导致对象结构不停地改变时,将那些比较稳定的属性与方法共用而提取的==继承==的实现。

Object.create() //ES5原生方法实现
function Person(){}
Person.prototype.name = "scater";
Person.prototype.age = 29;
Person.prototype.job = "web前端";
Person.prototype.sayName = function(){
   alert(this.name);
};
const scater = new Person();
scater.sayName(); // "scater "

==优点:==可以让所有对象实例共享它所包含的属性和方法

==缺点:==如果属性中存在引用类型,修改了会互相影响

混合模式(原型模式 + 构造函数模式)

创建自定义类型的最常见方式。

构造函数模式用于定义实例属性,而原型模式用于定义方法和共享的属性。

function Person(name, age, job){
    this.name = name;
    this.age = age;
    this.job = job;
    this.friends = ["Shelby", "Court"];
}
Person.prototype = {
    constructor : Person,
    sayName : function(){
        alert(this.name);
    }
}
var person1 = new Person("Nicholas", 29, "Software Engineer");
var person2 = new Person("Greg", 27, "Doctor");
person1.friends.push("Van");
alert(person1.friends); //"Shelby,Count,Van"
alert(person2.friends); //"Shelby,Count"
alert(person1.friends === person2.friends); //false
alert(person1.sayName === person2.sayName); //true

==优点:==每个实例都会有自己的一份实例属性的副本,但同时又共享着对方法的引用,最大限度地节省了内存。

动态原型模式

动态原型模式把所有信息都封装在了构造函数中,而通过在构造函数中初始化原型,又保持了同时使用构造函数和原型的优点。

可以通过检查某个应该存在的方法是否有效,来决定是否需要初始化原型。

function Person(name, age, job){
    //属性
    this.name = name;
    this.age = age;
    this.job = job;
    // 方法
    if (typeof this.sayName != "function"){
        Person.prototype.sayName = function(){
            alert(this.name);
        };
    }
}
const scater = new Person("scater", 29, "web前端");
scater.sayName(); // "scater"