让前端飞bb7bb的前端书屋程序员

JavaScript设计模式第一弹-创建型设计模式

2018-09-21  本文已影响20人  bb7bb

前言

接下来将会为大家介绍设计模式中的创建型设计模式,在此之前需要掌握一定的JavaScript对象继承基础。

简单工厂模式

先说说

看着定义有点懵,没关系。继续往下走

工厂函数

//定义小猫类
var Cat = function(){
    this.voice = '喵';
}
Cat.prototype.getVoice = function(){
    console.log(this.voice);
}

//定义小狗类
var Dog = function(){
    this.voice = '汪';
}
Dog.prototype.getVoice = function(){
    console.log(this.voice);
}

//动物工厂
var AnimalFactory = function(name) {
    switch(name){
        case 'cat':
            return new Cat();
        case 'dog':
            return new Dog();
    }
}

//创建实例
var hellokity = AnimalFactory('cat');
hellokity.getVoice();   //'喵'

当然,上面两种方法十分相似,于是还可以有下面的定义方式:

var createAnimal = function(name,voice) {
    var o = new Object(); 
    o.name = name;
    o.voice = voice;
    o.getVoice = function() {
        console.log(this.voice);
    }
    return o;
}
var hellokity = createAnimal('hellokity','喵');
hellokity.getVoice();   //'喵'

看似最后一种方法好像简便不少,但是实际上这两种定义方法是有区别的。

最后回顾

最后再次加深对简单工厂模式的印象吧

简单工厂模式:又叫静态工厂方法,由一个工厂对象决定创建某一种产品对象类的实例

工厂方法模式

先说说

懵?没关系。继续往下走

安全模式类

var Demo = function() {};
Demo.prototype.getName = function(){
    console.log('get success!')
}

var d = Demo();
d.getName();    //报错

//安全模式类
var Demo = function() {
    if(!(this instanceof Demo)){
        return new Demo
    }
};
Demo.prototype.getName = function(){
    console.log('get success!')
}

var d = Demo();
d.getName();    //'get success!'

工厂方法

实际上工厂方法和简单工厂模式区别在于:简单工厂模式如果需要增加类的话,那么它则需要改变两处地方,一处是工厂函数,一处是改变类。但是如果是工厂方法模式的话,则只需要往工厂方法中添加基类则可以。代码实现如下:

//安全模式创建的工厂类
var superHeroFatory = function(type,skill){
    if(this instanceof superHeroFatory){
        var s = new this[type](skill);
        return s
    }else{
        return new superHeroFatory(type,skill)
    }
}
superHeroFatory.prototype = {
    IronMan: function(skill){
        this.name = 'Iron Man';
        this.skill = skill;
        this.getName = function(){
            console.log(this.name);
        }
        this.getSkill = function(){
            console.log(this.skill);
        }
    },
    CaptainAmerica: function(skill){
        this.name = 'Captain America';
        this.skill = skill;
        this.getName = function(){
            console.log(this.name);
        }
        this.getSkill = function(){
            console.log(this.skill);
        }
    }
}

var captainAmerica = superHeroFatory('CaptainAmerica','shield');
captainAmerica.getName();   //'Captain America'
captainAmerica.getSkill();  //'shield'

最后回顾

这个工厂方法模式解决了创建多类对象所带来的麻烦,这样的工厂方法对象的方式也避免了使用者与对象类之间的耦合,用户不关心创建该对象的具体类,只需调用工厂方法即可。

抽象工厂模式

先说说

看着定义有点懵,没关系。继续往下走

抽象类

var Car = function() {};
Car.prototype = {
    getPrice(){
        return new Error('抽象方法不可用')
    },
    getName(){
        return new Error('抽象方法不可用')
    }
}

于是乎,在对象实例化后调用这些函数就会报错。因为抽象类是没有具体实现的,它只用作继承的方式

抽象工厂模式

var VehicleFactory = function(subType,superType){
    if(typeof VehicleFactory[superType] === 'function'){
        // 缓存类
        function F() { };
        
        //继承父类属性和方法
        F.prototype = new VehicleFactory[superType]();
        
        //子类constructor指向子类
        subType.constructor = subType;
        
        //子类原型继承“父类”
        subType.prototype = new F();
    }else{
        throw new Error('未创建该抽象类')
    }
}

//小汽车抽象类 
VehicleFactory.Car = function(){
    this.type = 'car';
}
VehicleFactory.Car.prototype = {
    getPrice(){
        return new Error('抽象方法不可用')
    },
    getName(){
        return new Error('抽象方法不可用')
    }
}

//大巴抽象类
VehicleFactory.Bus = function(){
    this.type = 'bus';
}
VehicleFactory.Bus.prototype = {
    getPrice(){
        return new Error('抽象方法不可用')
    },
    getName(){
        return new Error('抽象方法不可用')
    }
}

抽象类的实现

啥也别说了,直接上码

var BMW = function(price,name){
    this.price = price;
    this.name = name;
}
VehicleFactory(BMW,'Car');
BMW.prototype.getName = function(){
    console.log(this.name);
}

var X2 = new BMW(200,'X2');
X2.getName();   //'X2'
X2.getPrice();  //报错,因为忘记定义这个方法了

最后回顾

最后再次感受一下定义吧

抽象工厂模式:通过对类的工厂抽象使其业务用于对产品类簇的创建,而不负责创建其某一类产品的实例

建造者模式

先说说

与工厂模式差别

建造者模式

//创建类
var Human = function(props){
    this.name = props && props.name || '保密';
}
Human.prototype.getName = function(){
    console.log(this.name);
}

//名字类
var Name = function(name){
    var that = this;
    (function(name,that){
        that.wholeName = name;
        if(name.indexOf(' ') > -1){
            that.FirstName = name.slice(0,name.indexOf(' '));
            that.SecondName = name.slice(name.indexOf(' '));
        }
    })(name,that)
}


var Person = function(name){
    var _name = new Name(name);
    var _person = new Human({name:_name});
    return _person
}

var Miles = new Person('Miles Jiang');
Milse.getName();    //{wholeName: "Miles Jiang", FirstName: "Miles", SecondName: " Jiang"}

最后回顾

这种模式下,我们就可以关心到对象的创建过程。因此我们通常将创建对象模块化,这样使得被创建的类的每个模块都可以获得灵活的运用和高质量的复用

单例模式

先说说

命名空间

var Miles = {
    getDom: function(id){
        return document.getElementById(id)
    }
}

最后回顾

为了梳理代码,使得代码有序整洁

后话

本文章是通过学习张荣铭所著的《JavaScript设计模式》所总结。希望大家看完文章可以学到东西,同时也推荐大家去看看这本设计模式,写得很不错。

成功不在一朝一夕,我们都需要努力

上一篇 下一篇

猜你喜欢

热点阅读