2009年9月3日星期四

[note]工厂模式与Prototype模式

<<<难得自己写篇技术性的文章。今天看Javascript的prototype时一直不理解,于是反过来看Prototype设计模式,终于对此设计模式有所了解。难得原创一次,转帖请注明来源>>>

1.工厂模式

工厂模式主要的优点在于提供一个统一的接口,用户“生产”某一“类别的产品”。

列入生产汽车的情况下,我们写好了汽车类如下:
public class Car {
    private String name;

    public Car(String name) {
            this.name = name;
    }
}
不使用工厂模型时,我们要汽车就需要自己去“造”一辆,如下:
Car myCar = new Car("carName");
你只造一种车还好,但是如果我们要造很多种车:中国车、日本车、美国车...就需要更多继承自Car的类,如下:
public class ChineseCar extend Car {    
     public ChineseCar (String _name) {
         name = _name; 
         //中国车特有的改造
         ...
     }
}

public class JapaneseCar extend Car {    
     public JapaneseCar(String _name) {
         name = _name; 
         //日本车特有的改造
         ...
     }
}

public class AmericanCar extend Car {    
     public AmericanCar(String _name) {
         name = _name; 
         //美国车特有的改造
         ...
     }
}
没错,现在只有三种车,你自己做起来不麻烦。当车的种类越来越多时就麻烦了,不过有更好的方法,就是用工厂模式。
public class CarFactory {
    public Car buildCar(String carName,String carType) {
           if (carType.equal("中国"))
                     return new ChineseCar(carName);
           ......
    }
}
这样你只需要知道要什么车,只去找工厂而已。或许你说都知道要“中国”车了,当然就是new ChineseCar()了,用工厂模式浪费了。我本来也觉得如此,但是这个工厂比较简单,我们可以有专门的客户服务部,专门找到你想要的车,你就可以模糊查找等等方式!而不必用 if (carType.equal("中国"))这样简单的比较方法。比如以下的方法:
public class CarFactory2 {
    public Map<String,String>  menu = new Map<String,String>();

    public CarFactory() {}

    public Car buildCar(String carName,String carType) {
           // 搜索class的名字
           String className = menu.get(carType);
           Object[] args = new Object[1];
           args[0] = carName;
           // 动态创建实例
           return newInstance(className,args);
    }

    // 动态创建实例
    public Object newInstance(String className, Object[] args) throws Exception {   
          Class newClass = Class.forName(className);
          Class[] argsClass = new Class[args.length];
          
          for (int i = 0, j = args.length; i < j; i++) {
                  argsClass[i] = args[i].getClass();
          }

           Constructor cons = newClass.getConstructor(argsClass);

           return cons.nesInstance(args);
     }

     public void addNewType(String carType, String name) {
           ...
     }
}

2.Prototype模式

Prototype模式最大的优点是:不再需要一个与具体产品等级结构平行的类结构,减少了类的构造,同时客户程序可以在运行时刻建立和删除原型。

同样是上述的一个例子,当又有新车发售时,大家都去买车。公司给工厂一个的设计图,工厂就要从头增加一条新的生产线。在类图中的表现就是Car的子类越来越多,CarFactory的buildCar方法一直在变,即使是比较“厉害”的CarFacotry2的menu也一直在变长!
如果每辆车的设计都是完全不一样的那么这样也无妨。但是市场上那么多车都不过是四个轮子、有反光镜、有后视镜等等共同的特征,更甚至有无良的山寨厂商改了型号当自己新车上市。这时工厂在去为这种毫无创新的新车开辟新的生产线,那真是脑子有问题了。所以精明的厂长总是会重复利用。

我们假设车之间不一样的只有颜色而已(设计者很懒),这样工厂可以先生产没上色的车的原型,再根据设计图涂上颜色。这样只用一条生产线解决n调的问题。多好!
public class PrototypeCar implement Clonable {
        public String color = "white";
        public String name = "prototype";
        public PrototypeCar() {}
        @Override
        public Object clone() {
               PrototypeCar c = null;
               try {
                   c = (PrototypeCar)super.clone();
               }catch (CloneNotSupportedException e) { 
                   e.printStackTrace(); 
               }
               return c;
        }
        public void setColor(String color) {
              this.color = color;
       }
       public void setName(String name) {
             this.name= name;
       }
}

public class CarFactory {
    private PrototypeCar prototype = new PrototypeCar();

    public CarFactory() {...}

    public Car buildCar(String carName,String carColor) {
           prototype.setName(carName);
           prototype.setColor(carColor);
    }

    public void addNewType(String carType, String name) {
           ...
     }
}
这样我只需要两个类就可以解决问题了,是不是很方便。

没有评论: