技术开发 频道

在Java中应用设计模式-Factory Method


  1.e 测试类:请注意这个客户端程序多么简洁,既没有罗嗦的条件判断语句,也无需关心ConcreteProduct和ConcreteCreator的细节(因为这里我用anOperation封装了Product里的两个方法,所以连Product的影子也没看见,当然把Product里方法的具体调用放到客户程序中也是不错的).
class Main { public static void main(String[] args){ ShapeFactory sf1 = new SquareFactory(); ShapeFactory sf2 = new CircleFactory(); sf1.anOperation("Shape one"); sf2.anOperation("Shape two"); } }
  运行结果如下:
The current shape is: Shape one (created by SquareFactory)   It will draw a square.   It will erase a square.   The current shape is: Shape two (created by CircleFactory)   It will draw a circle.   It will erase a circle.
  参数化的Factory Method: 这种方式依靠指定的参数作为标志来创建对应的实例,这是很常见的一种办法.比如JFC中的BorderFactory就是个很不错的例子. 以下的这个例子是用字符串作为标记来进行判断的,如果参数的类型也不一样,那就可以用到过载函数来解决这个问题,定义一系列参数和方法体不同的同名函数,这里java.util.Calendar.getInstance()又是个极好的例子.参数化的创建方式克服了Factory Method模式一个最显著的缺陷,就是当具体产品比较多时,我们不得不也建立一系列与之对应的具体构造器. 但是在客户端我们必须指定参数来决定要创建哪一个类.

  2.a 我们在第一种方法的基础上进行修改,首先自定义一个的异常,这样当传入不正确的参数时可以得到更明显的报错信息.
class NoThisShape extends Exception { public NoThisShape(String aName) { super(aName); } }
  2.b 去掉了ShapeFactory的两个子类,改为由ShapeFactory直接负责实例的创建. ShapeFactory自己变成一个具体的创建器,直接用参数化的方法实现factoryMethod返回多种对象.
abstract class ShapeFactory { private static Shape s; private ShapeFactory() {} static Shape factoryMethod(String aName, String aType) throws NoThisShape{ if (aType.compareTo("square")==0) return new Square(aName); else if (aType.compareTo("circle")==0) return new Circle(aName); else throw new NoThisShape(aType); } // 在anOperation中定义Shape的一系列行为 static void anOperation(String aName, String aType) throws NoThisShape{ s = factoryMethod(aName, aType); System.out.println("The current shape is: " + s.name); s.draw(); s.erase(); } }
  2.c 测试类:这里客户端必须指定参数来决定具体创建哪个类.这个例子里的anOperation是静态函数,可以直接引用.
class Main { public static void main(String[] args) throws NoThisShape{ ShapeFactory.anOperation("Shape one","circle"); ShapeFactory.anOperation("Shape two","square"); ShapeFactory.anOperation("Shape three", "delta"); } }
  运行结果如下:
The current shape is: Shape one   It will draw a circle.   It will erase a circle.   The current shape is: Shape two   It will draw a square.   It will erase a square.   Exception in thread "main" NoThisShape: delta at ShapeFactory.factoryMethod(ShapeFactory.java:10) at ShapeFactory.anOperation(ShapeFactory.java:15) at Main.main(Main.java:5)
  动态装载机制:

  有的时候我们会把ConcreteProduct的实例传给创建器作为参数,这种情况下,如果在创建器里完成创建过程,就必须判断参数的具体类型(用instanceof),然后才能产生相应的实例,那么比较好的做法是利用Java的动态装载机制来完成这件事.比如:

  我们得到一个Shape的子类s,但不知道具体是那个子类,就可以利用Class类自带的方法newInstance()得到实例
return (Shape)s.getClass().newInstance();
  这种方法有兴趣得读者可以自己尝试,限于篇幅,不写具体代码出来了.

  后话:

  看完这篇文章后,相信读者对Factory Method模式有一个比较清楚的了解了.我想说的是,我们不仅应该关心一个具体的模式有什么作用,如何去实现这个模式,更应该透过现象看本质,不但知其然,还要知其所以然.要通过对模式的学习加深对面向对象思想的理解,让自己的认识得到升华.Factory Method模式看似简单,实则深刻.抽象,封装,继承,委托,多态,针对接口编程等面向对象中的概念都在这里得到了一一的体现.只有抓住了它的本质,我们才能够不拘于形式的灵活运用,而不是为了使用模式而使用模式.
0
相关文章