1

工厂设计模式

工厂设计模式, 顾名思义就是生产对象的工厂, 在这里需要注意的是生产的对象都是同一规格的, 具有某些相同的特性, 否则工厂模式的意义荡然无存
接口在工厂模式中有着重要的作用, 如果对生产的对象不实现某个接口, 试问我们为什么还要工厂模式, 工厂模式使得我们创建的所有事例可以一视同仁, 屏蔽了不同对象的区别, 因为他们实现的同样的接口

简单工厂

简单工厂就是工厂所生产的产品虽然都符合接口规范, 但产品无法分类, 这里简单举一个商店出售自行车的例子, 则所生产的自行车都实现了自行车的规范, 但自行车无法分辨厂家

    let BicycleShop = (function () {
    
      /* BicycleFactory namespace. */
      let BicycleFactory = {
        createBicycle: function(model) {
          let 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 class, improved. */
    
      let BicycleShop = function() {};
      BicycleShop.prototype = {
        sellBicycle: function(model) {
          var bicycle = BicycleFactory.createBicycle(model);
          
          bicycle.assemble();
          bicycle.wash();
          
          return bicycle;
        }
      };
      return BicycleShop;
    
    })();

    /* The Bicycle interface. */
    
    var Bicycle = new Interface('Bicycle', ['assemble', 'wash', 'ride', 'repair']);
    
    /* Speedster class. */
    
    var Speedster = function() { // implements Bicycle
      ...
    };
    Speedster.prototype = {
      assemble: function() {
        ...
      },
      wash: function() {
        ...
      },
      ride: function() {
        ...
      },
      repair: function() {
        ...
      }
    };
    
    
    /* Usage. */
    
    var californiaCruisers = new BicycleShop();
    var yourNewBike = californiaCruisers.sellBicycle('The Speedster');

图片描述

简单工厂的弊端在于所有的对象都有工厂类来实现, 无法对对象分类, 降低了拓展性, 比如如果有膜拜自行车专卖店和ofo自行车专卖店呢, 所以简单的业务简单工厂就够了, 如果面对复杂业务逻辑则需要抽象工厂模式

抽象工厂

真正的工厂模式与简单工厂区别在于, 它不是使用工厂类来生产对象的, 而是使用其子类, 将其成员对象的实例化推迟到子类中, 这样就可以对自行车进行分类, 例如工厂类为接口或抽象类, 膜拜自行车工厂和ofo自行车工厂为子类, 当然这两家的自行车都实现了自行车接口, 下面如图所示;
图片描述

首先定义一个工厂类

    var BicycleShop = (function() {
    
      let BicycleShop = function() {};
      BicycleShop.prototype = {
        sellBicycle: function(model) {
          var bicycle = this.createBicycle(model);      
          return bicycle;
        },
        createBicycle: function(model) {
          throw new Error('Unsupported operation on an abstract class.');
        }
      };
      return  BicycleShop
    })();

然后定义多个继承工厂类的基于分类的类

    let AcmeBicycleShop = (function() {
    
      /* AcmeBicycleShop class. */
    
      let AcmeBicycleShop = function() {};
      extend(AcmeBicycleShop, BicycleShop);
      AcmeBicycleShop.prototype.createBicycle = function(model) {
        let 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;  
      };
      return AcmeBicycleShop
    })();
    
    var GeneralProductsBicycleShop = (function() {
    
      /* GeneralProductsBicycleShop class. */
    
      let GeneralProductsBicycleShop = function() {};
      extend(GeneralProductsBicycleShop, BicycleShop);
      GeneralProductsBicycleShop.prototype.createBicycle = function(model) {
        let 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;
      };
    
    
    })();

最后使用

    /* Usage. */
    
    var alecsCruisers = new AcmeBicycleShop();
    var yourNewBike = alecsCruisers.sellBicycle('The Lowrider');
    
    var bobsCruisers = new GeneralProductsBicycleShop();
    var yourSecondNewBike = bobsCruisers.sellBicycle('The Lowrider');
抽象工厂模式可以把公共代码放在父类中, 个体性的代码放在子类中, 责任分离的同时提高拓展性

镰月
313 声望13 粉丝

它的优秀之处并非原创,它的原创之处并不优秀。