简单工厂模式(创建单一的对象)

示例1

描述

工厂模式主要是为了创建对象实例或者类簇(抽象工厂), 关心的是最终产出(创建)的对象, 而不关心创建的过程.

在出现多个类的时候, 每次创建需要找到对应的类往往比较麻烦, 这时候通常使用一个函数进行封装来创建所需要的对象,
这样就无需关注创建这些对象到底依赖哪些基类了, 只要知道有这个函数就可以了, 通常这个函数被称为工厂函数,
这种模式叫简单工厂模式

案例

假设一体育商品店卖器材, 里面有很多体育商品, 及其相关介绍. 当你来到体育用品店买一个篮球及相关介绍时,
你只需要问售货员, 她会帮你找到你所需要的东西.

实现

// 篮球基类
var Basketball = function() {
    this.intro = '篮球盛行于美国';
}
Basketball.prototype = function() {
    getMember: function() {
        console.log('每个队伍需要5名队员');
    },
    getBallSize: function() {
        console.log('篮球很大');
    }
}

// 足球基类
var Football = function() {
    this.intro = '足球在世界范围内盛行';
}
Football.prototype = function() {
    getMember: function() {
        console.log('每个队伍需要11名队员');
    },
    getBallSize: function() {
        console.log('足球很大');
    }
}

// 网球基类
var Tennis = function() {
    this.intro = '每年有很多网球系列赛';
}
Tennis.prototype = function() {
    getMember: function() {
        console.log('每个队伍需要1名队员');
    },
    getBallSize: function() {
        console.log('网球很小');
    }
}

// 运动工厂(这边相当于咨询体育器材店的售货员, 告诉她你想要买什么体育用品)
var SportFactory = function(name) {
    switch(name) {
        case 'basketball':
            return new Basketball();
        case 'football':
            return new Football();
        case 'tennis':
            return new Tennis();
    }
}

var ball = new SportFactory('tennis');
console.log(ball.intro)            // 每年有很多网球系列赛
console.log(ball.getMember());    // 每个队伍需要1名队员

示例2

描述

简单工厂模式的理念就是创建对象, 而除此之外, 简单工厂模式还可以创建相似对象. 在创建多个类的时候, 假设每个类都有很多相似的地方, 比如在多种弹出框上都有关闭按钮, 都有提示文案等. 可以通过将这些相似的东西提取, 不相似针对性处理即可.

案例

假设当前项目需求是需要做各种弹出框: 警示框, 确认框及提示框.

实现

var LoginAlert = function(text) {
    this.content = text;
};
LoginAlert.prototype.show = function() {
    // 显示警示框
};

var LoginConfirm = function(text) {
    this.content = text;
};
LoginConfirm.prototype.show = function() {
    // 显示确认框
};

var LoginPrompt = function(text) {
    this.content = text;
};
LoginPrompt.prototype.show = function() {
    // 显示提示框
};

function createPop(type, text) {
    var o = new Object();
    o.content = text;
    o.show = function() {
        // 显示方法
    };
    if(type === 'alert') {
        // 警示框差异部分
    }
    if(type === 'confirm') {
        // 确认框差异部分
    }
    if(type === 'prompt') {
        // 提示框差异部分
    }

    return o;
}

// 创建警示框
var userNameAlert = createPop('alert', '用户名只能是26个字母和数字');

工厂方法模式(创建多类对象)

示例

描述

通过对产品类的抽象使其创建业务主要负责用于创建多类产品的实例.

案例

假设有一批关于计算机培训的广告资源需要投放, 一批是PHP要求黄色字体红色背景, 一批JAVA绿色字体,
一批JAVASCRIPT粉色背景....

实现

var Java = function(content) {
    this.content = content;
    (functiont(content) {
        var div = document.createElement('div');
        div.innerHTML = content;
        div.style.color = 'green';
        document.getElementById('container').appendChild(div);
    })(content);
};

var Php = function(content) {
    this.content = content;
    (functiont(content) {
        var div = document.createElement('div');
        div.innerHTML = content;
        div.style.color = 'yellow';
        div.style.background = 'red';
        document.getElementById('container').appendChild(div);
    })(content);
};

var Javascript = function(content) {
    this.content = content;
    (functiont(content) {
        var div = document.createElement('div');
        div.innerHTML = content;
        div.style.background = 'pink';
        document.getElementById('container').appendChild(div);
    })(content);
};

// 创建学科类工厂
function JobFactory(type, content) {
    switch(type) {
        case 'java':
            return new Java(content);
        case 'php':
            return new Php(content);
        case 'Javascript':
            return new Javascript(contet);
    }
}

// 又要添需求啦.....多加一批UI学科, 红色边框.....

// 代码改进:

var Factory = function(type, content) {
    if(this instanceof Factory) {
        var s = new this[type] (content);
        return s;
    } else {
        return new Factory(type, content);
    }
};

// 在工厂原型中设置创建所有类型数据对象的基类
Factory.prototype = {
    Java: function() {
        // ...
    },
    Php: function() {
        // ...
    },
    Javascript: function() {
        // ...
    },
    UI: function() {
        // ...
    }
};

var data = [
    {type:'JavaScript', content:'javascript'},
    {type:'Java', content:'java'},
    {type:'PHP', content:'php'},
    {type:'UI', content:'ui'}
];

for(var i = data.length; i >= 0; i--) {
    Factory(data[i].type, data[i].content);
}

抽象工厂模式(创建类簇)

示例

描述

抽象工厂模式一般不用来创建具体对象, 抽象类中定义的方法只是显性地定义一些功能, 但没有具体的实现, 而一个对象需要具有一套完整的功能, 所以用抽象类创建的对象也是抽象的而非真实对象. 因此一般用它作为父类来创建子类.

抽象工厂其实是一个实现子类继承父类的方法, 在这个方法中需要通过传递子类以及要继承父类(抽象类)的名称,并且在抽象工厂方法中又增加了一次对抽象存在性的一次判断, 如果存在, 则将子类继承父类的方法. 然后子类通过寄生式继承.继承父类的原型中需要注意一点是, 在对过渡类的原型继承时, 不是继承父类的原型, 而是通过new关键字复制父类的一个实例, 这么做事因为过渡类不应仅仅继承父类的原型方法, 还要继承父类的对象属性, 所以要通过new关键字将父类的构造函数执行一遍来复制构造函数中的属性和方法

抽象工厂添加抽象类比较特殊, 因为抽象工厂是个方法不需要实例化对象, 故只需要一份, 因此直接为抽象工厂添加类的属性即可.

实现

// 抽象工厂方法
var VehicleFatory = 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: function() { return new Error('抽象方法不能调用'); },
    getSpeed: function() { return new Error('抽象方法不能调用'); }
};

// 公交车抽象类
VehicleFactory.Bus = function() {
    this.type = 'bus';
};
VehicleFactory.Bus.prototype = {
    getPrice: function() { return new Error('抽象方法不能调用'); },
    getSpeed: function() { return new Error('抽象方法不能调用'); }
};

// 货车抽象类
VehicleFactory.Truck = function() {
    this.type = 'truck';
};
VehicleFactory.Truck.prototype = {
    getPrice: function() { return new Error('抽象方法不能调用'); },
    getSpeed: function() { return new Error('抽象方法不能调用'); }
};

// 创建产品子类继承相应的产品簇抽象类
// 宝马汽车子类
var BMW = function(price, speed) {
    this.price = price;
    this.speed = speed;
}
//抽象工厂实现对Car抽象类的继承
VehicleFactory(BMW, 'Car');
BMW.prototype.getPrice = function() { return this.price };
BMW.prototype.getSpeed = function() { return this.speed };

// 公交车...
// 货车...

引路人
146 声望12 粉丝