工厂模式

文中示例代码引用自《Javascript设计模式》一书

使用工厂模式的目的

消除对象间的耦合,简化更换所使用的类的工作以及简化在运行期间动态选择所用类的工作。(即弱化对象间耦合以及防止代码的重复)

工厂模式的思路

先创建出所要用到的小对象,然后生成并返回包含这些小对象的容器,即大对象。

示例

自行车商店

非工厂模式

不同自行车店,卖不同类自行车

var BicycleShop = function () { };
    BicycleShop.prototype = {
        sellBicycle: function (model) {
            var bicycle;
            switch (model) {
                case 'The Speedster':
                    bicycle = new Speedster();
                    break;
                case 'The Lowrider':
                    bicycle = new Lowrider();
                    break;
                case 'The Comfort Cruiser':
                default:
                    bicycle = new ComfortCruiser();
            }
            Interface.ensureImplements(bicycle, Bicycle);
            bicycle.assemble();
            bicycle.wash();
            return bicycle;
        }
    };
无论哪家自行车店,都具有该服务,即各类自行车店都实现了该自行车接口。
var Bicycle = new Interface('Bicycle', ['assemble', 'wash', 'ride', 'repair']);
    var Speedster = function () { ...};
    Speedster.prototype={
        assemble:function(){
            ...
        },
        wash:function(){
            ...
        },
        ride:function(){
            ...},
        repair:function(){
            ...
        }
    };
有某种自行车,要卖掉
 var californiaCruisers = new BicycleShop();
    var yourNewBike = californiaCruisers.sellBicycle('The Speedster');
若现在增加了某个新的种类的自行车店,则需要对BIcycleShop这一个大类进行更改,即代码的耦合性较高,牵一发而动全身

工厂模式

经常发生变动的小对象被分离出来,生成一个函数

  var BicycleShop = function () { };
    BicycleShop.prototype = {
        sellBicycle: function (model) {
            var bicycle=this.createBicycle(model);
            bicycle.assemble();
            bicycle.wash();
            return bicycle;
        },
        createBicycle: function (model)
        {
            var bicycle;
            switch (model) {
                case 'The Speedster':
                    bicycle = new Speedster();
                    break;
                case 'The Lowrider':
                    bicycle = new Lowrider();
                    break;
                case 'The Comfort Cruiser':
                default:
                    bicycle = new ComfortCruiser();
            }
            Interface.ensureImplements(bicycle, Bicycle);
            return bicycle;
        }
    };

这样,当产生新种类自行车的商店时,我们只需要改变BicycleShop.createBicycle函数,即
BicycleShop.createBicycle=function (model)
        {
            var bicycle;
            switch (model) {
                case 'The Speedster':
                    bicycle = new Speedster();
                    break;
                case 'The Lowrider':
                    bicycle = new Lowrider();
                    break;
                case 'The FlatLander':
                    bicycle = new Flatlander();
                    break;
                case 'The Comfort Cruiser':
                default:
                    bicycle = new ComfortCruiser();
            }
            Interface.ensureImplements(bicycle, Bicycle);
            return bicycle;
        }
而不是改变一个BicycleShop大类,这样一来耦合性大大降低。
再比如现在除了增加不同类别自行车的店,还增加了不同进货渠道的信息,不同的进货渠道的自行车在不同的店卖,不同类别的自行车也在不同的店卖。
我们通过继承,来分别定义不同进货渠道下,不同类自行车的所在店。比如有两个进货渠道,Acme和General Products公司。
则这两个进货渠道分别继承BicycleShop这一类。

var AcmeBicycleShop = function () { };
    extend(AcmeBicycleShop, BicycleShop);
    AcmeBicycleShop.prototype.createBicycle = function (model) {
        var bicycle;
        switch (model) {
            case 'The Speedster':
                bicycle = new AcmeSpeedster();
                break;
            case 'The Lowrider':
                bicycle = new AcmeLowrider();
                break;
            case 'The FlatLander':
                bicycle = new AcmeFlatlander();
                break;
            case 'The Comfort Cruiser':
            default:
                bicycle = new AcmeComfortCruiser();
        }
        Interface.ensureImplements(bicycle, Bicycle);
        return bicycle;
    }
var GeneralProductsBicycleShop = function () { };
    extend(GeneralProductsBicycleShop, BicycleShop);
    GeneralProductsBicycleShop.prototype.createBicycle = function (model) {
        var bicycle;
        switch (model) {
            case 'The Speedster':
                bicycle = new GeneralProductsSpeedster();
                break;
            case 'The Lowrider':
                bicycle = new GeneralProductsLowrider();
                break;
            case 'The FlatLander':
                bicycle = new GeneralProductsFlatlander();
                break;
            case 'The Comfort Cruiser':
            default:
                bicycle = new GeneralProductsComfortCruiser();
        }
        Interface.ensureImplements(bicycle, Bicycle);
        return bicycle;
    }

XHR工厂的动态定义函数

   var AjaxHandler = new Interface('AjaxHandler', ['request', 'createXhrObject']);
    var SimpleHandler = function () {};
    SimpleHandler.prototype={
        request:function(method,url,callback,postVars){
            var xhr=this.createXhrObject();
            xhr.onreadystatechange=function(){
                ...
            };
            xhr.open(method,rul,true)
        },
        createXhrObject:function(){
            var methods=[
                function(){return new XMLHttpRequest();},
                function(){return new ActiveXObject('Msxml2.XMLHTTP');},
                function(){return new ActiveXObject('Microsoft.XMLHTTP');}
            ];
            for(var i=0,len=methods.length;i<len;i++){
            
                try{
                    methods[i]();
                }
                catch(e){
                    continue;
                }
                this.createXhrObject=methods[i]//memoize the method。
                //运行过一次该位置后,实例化对象.createXhrObject就根据其首次运行的浏览器环境被指向对应的方法了
                //再次执行request函数时,其调用的createXhrObject函数就是这个被赋值的函数,而不用再重新判断一遍
                //即动态定义函数
                return methods[i];
                throw new Error('SimpleHandler:Could not create an XHR object')
            }
        }
    }

注意,该模式并非什么时候都是合适的模式,当以下两种情况时,最好用new关键字和构造函数公开进行实例化,这样可以简化代码结构,增强代码的易读性,可以一眼就看到调用的是什么构造函数,而不用去查看某个工厂方法才能知道实例化的是什么类。
  • 根本不可能另外换用该类
  • 不需要在运行期间在可互换类中动态进行选择时,
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值