27 March 2014

百度百科上对设计模式做了如下解释:

设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。

设计模式本身是一种经验的总结,就像一个人的境界,不是学能学会的,而是要不停的历练。设计模式便是这种,需要不断实践才能领悟的技巧。

今天研究了一下“工厂方法设计模式”,《Java编程思想》中做了简单的介绍。看下面代码:

interface Service {
  void method1();
  void method2();
}

interface ServiceFactory {
  Service getService();
}

class Implementation1 implements Service {
  Implementation1() {}
  public void method1() {print("Implementation1 method1");}
  public void method2() {print("Implementation1 method2");}
}    

class Implementation1Factory implements ServiceFactory {
  public Service getService() {
    return new Implementation1();
  }
}

class Implementation2 implements Service {
  Implementation2() {}
  public void method1() {print("Implementation2 method1");}
  public void method2() {print("Implementation2 method2");}
}

class Implementation2Factory implements ServiceFactory {
  public Service getService() {
    return new Implementation2();
  }
}    

public class Factories {
  public static void serviceConsumer(ServiceFactory fact) {
    Service s = fact.getService();
    s.method1();
    s.method2();
  }
  public static void main(String[] args) {
    serviceConsumer(new Implementation1Factory());
    // Implementations are completely interchangeable:
    serviceConsumer(new Implementation2Factory());
  }
} /* Output:
Implementation1 method1
Implementation1 method2
Implementation2 method1
Implementation2 method2
*/

初看,最直观的印象是多态,没错,似乎是多态的实现。书中似乎没有对这种模式做出很详细的介绍,但就那仅有的几句已经说明了很多问题,比如:

通过这种方式,我们的代码将完全与接口的实现分离。这就使得我们可以透明地将某个实现替换为另一个实现。

如果不是用工厂方法,你的代码就必须在某处指定将要创建的Service的确切类型,以便调用合适的构造器。

什么意思呢?不了解。不过到这里,我却有了一个疑问,为什么要工厂而不能直接使用多态。将上例做一下修改:

public class Factories {
  public static void serviceConsumer(ServiceFactory fact) {
    Service s = fact.getService();
    s.method1();
    s.method2();
  }
 
  public static void serviceConsumer2(Service fact) {
       Service s = fact;
       s.method1();
       s.method2();
  }
  public static void main(String[] args) {
       serviceConsumer2(new Implementation1());
       serviceConsumer2(new Implementation2());
  }
}

结果完全一致,而且更直接。

于是我开始搜索网页、书籍。竟然出现了更多的问题,什么简单工厂模式,工厂方法模式,抽象方法模式,权责单一,解耦都出来了。又看了《大话设计模式》关于工厂模式的一节,竟然问题越来越多。折腾了好几个小时。

比如,为什么简单工厂模式对输入要判断,而工厂方法模式却不需要(工厂方法模式的一个重要优点就是符合封闭原则即只扩展不修改)。就这一个问题,纠结了很长时间。最后,发现是我对这个设计模式的理解有问题。

就拿这个问题来说,要考虑“工厂”这个概念。比如,有个汽车厂什么车都生产(简单工厂原则),你说要辆奔驰,工厂要进行判断,找到奔驰车,然后再给你(这就是判断过程的意义)。那为什么工厂方法模式不需要?因为它为每一类车都创建了工厂,你要奔驰车直接找奔驰车厂就行,奔驰车厂只负责生产奔驰车。

所以,绝不仅仅是代码实现那么简单,而是背后的理论概念。所以,简单工厂模式如果加一种新车,要写一个新车的类(扩展)还要修改汽车厂(添加新车)。但是工厂方法模式显然就不需要修改,你只需要扩展新车的类和新车的工厂即可。

那么,本文第一个问题该如何解释?其实,这就是为什么要用工厂方法模式了。我的同学告诉我:

工厂里面不仅可以返回一个对象,还能做很多事情。当你new多了就不想new了。

说实在的,有点感觉,但还是不懂。随后在网上浏览,发现对于这个问题,基本都看不懂。

为什么会出现这种问题?因为设计模式本身就是经验的总结,如果没有经验,当然会不容易看懂。就像绝世武功,非有几十年功力不能学会。

没错,想真正学会这些设计模式,需要不断的实践。经验这种东西,不是靠天赋就能弥补的,要靠不断实践。研究“工厂设计模式”的经历给我上了重要的一课。

最后给一个用内部类实现的工厂方法模式,更加简洁优美:

interface Service {
  void method1();
  void method2();
}

interface ServiceFactory {
  Service getService();
}    

class Implementation1 implements Service {
  private Implementation1() {}
  public void method1() {print("Implementation1 method1");}
  public void method2() {print("Implementation1 method2");}
  public static ServiceFactory factory =
    new ServiceFactory() {
      public Service getService() {
        return new Implementation1();
      }
    };
}    

class Implementation2 implements Service {
  private Implementation2() {}
  public void method1() {print("Implementation2 method1");}
  public void method2() {print("Implementation2 method2");}
  public static ServiceFactory factory =
    new ServiceFactory() {
      public Service getService() {
        return new Implementation2();
      }
    };
}    

public class Factories {
  public static void serviceConsumer(ServiceFactory fact) {
    Service s = fact.getService();
    s.method1();
    s.method2();
  }
  public static void main(String[] args) {
    serviceConsumer(Implementation1.factory);
    serviceConsumer(Implementation2.factory);
  }
}


blog comments powered by Disqus