Chinaunix首页 | 论坛 | 博客
  • 博客访问: 443786
  • 博文数量: 97
  • 博客积分: 1552
  • 博客等级: 上尉
  • 技术积分: 1091
  • 用 户 组: 普通用户
  • 注册时间: 2012-05-17 17:05
个人简介

专注于大规模运维场景运维工具解决方案。欢迎有这方面兴趣的朋友跟我联系。

文章分类

全部博文(97)

文章存档

2014年(12)

2013年(25)

2012年(60)

我的朋友

分类: Java

2012-07-28 15:41:06

Factory Method模式
1、模式简介
设计模式的简单定义就是对于一类重复出现的问题的可重用的解决方案。在软件工程中一个设计模式解决一类软件设计问题。
在《设计模式》一书中涉及到23个模式,被分类为创建型模式(Creational Patterns),结构型模式(Structural Patterns)和行为模式(Behavioral Patterns),分别从对象的创建,对象和对象间的结构组合以及对象交互这三个方面为面向对象系统建模方法给予了解析和指导。
其中创建型设计模式(Creational Patterns)描述怎样创建一个对象。它隐藏对象创建的细节,使程序代码不依赖具体的对象,这样当我们增加一个新的对象时几乎不需要修改代码。结构型设计模式(Structural Patterns)描述类和对象之间怎么组织起来形成大的结构,主要使用继承来组织接口或实现。行为型设计模式(Behavioral Patterns)描述算法以及对象之间的任务分配,它所描述的不仅仅是对象或类的设计模式,还有它们之间的通讯模式。
2、设计模式之Factory Method

此模式属于创建型设计模式,它只定义创建对象的接口,而由它的子类负责创建具体的对象,利用子类实例化不同的对象。图一是Factory Method 模式结构的类图(Class Diagram),其中:

  1. Product 定义了由factory method所创建对象的统一接口.
{见下面的Shape.java文件}
  1. ConcreteProduct 具体的类,实现Product接口。
{见下面的Square.java文件,它实现了一个具体的类}
  1. Creator 一般为抽象类,声明若干factory method(方法),由它创建类型为Product的对象。正因为它能"生产"对象,所以称为factory method。Creator也可能拥有一个方法创建某个缺省的具体对象。[工厂类生产对象用的]
{见下面的ShapeFactory.java类}

  1. ConcreteCreator 重载factory method以创建某个 ConcreteProduct 的具体实例.
{见下面的SquareFactory.java类 表示创建具体的一个类}

也就是说Creator依赖于ConcreteCreator创建Product型的ConcreteProduct对象。 Factory method使应用程序代码只需处理Product接口,而与具体的类(ConcreteProduct)无关,增强了代码可重用性,因为它独立于用户定义的具体的类。


3、一个JAVA实例
1.a 首先定义一个抽象类Shape,定义两个抽象的方法.

点击(此处)折叠或打开

  1. public abstract class Shape {
  2.     public String name;
  3.     public Shape(String aName) {
  4.         name = aName;
  5.     }
  6.     public abstract void draw();
  7.     public abstract void erase();
  8. }
1.b 定义 Shape的两个子类: Circle, Square,实现Shape中定义的抽象方法

点击(此处)折叠或打开

  1. public class Circle extends Shape{

  2.     @Override
  3.     public void draw() {
  4.         // TODO Auto-generated method stub
  5.         System.out.println("It will draw a circle.");
  6.     }

  7.     @Override
  8.     public void erase() {
  9.         // TODO Auto-generated method stub
  10.         System.out.println("It will erase a circle.");
  11.     }
  12.     public Circle(String name){
  13.         super(name);
  14.     }
  15. }
  16. public class Square extends Shape{

  17. @Override
  18. public void draw() {
  19. // TODO Auto-generated method stub
  20. System.out.println("It will draw a Square.");
  21. }

  22. @Override
  23. public void erase() {
  24. // TODO Auto-generated method stub
  25. System.out.println("It will erase a Square.");
  26. }
  27. public Square(String aName){
  28. super(aName);
  29. }
  30. }
1.c 定义抽象的创建器,anOperation调用factoryMethod创建一个对象,并对该对象进行一系列操作.

点击(此处)折叠或打开

  1. public abstract class ShapeFactory {
  2. //这就是为什么叫做ShapeFactory了。因为它不关心具体的实现的。只关心 [接口/抽象类]
  3.     protected abstract Shape factoryMethod(String aName);
  4.     //在anOperation定义Shape的一系列行为
  5.     public void anOperation(String aName) {
  6.         Shape s = factoryMethod(aName);
  7. //创建一个接口对象。子类想怎么实现就怎么实现
  8.         System.out.println("The current shape is: " + s.name);
  9.         s.draw();
  10.         s.erase();
  11.     }
  12. }
1.d 定义与circle和square相对应的两个具体创建器CircleFactory,SquareFactory,实现父类的methodFactory方法

点击(此处)折叠或打开

  1. public class CircleFactory extends ShapeFactory {

  2.     @Override
  3.     protected Shape factoryMethod(String aName) {
  4.         // TODO Auto-generated method stub
  5.         return new Circle(aName + "(created by CircleFactory)");
  6.     }
  7. }

  8. public class SquareFactory extends ShapeFactory {

  9.     @Override
  10.     protected Shape factoryMethod(String aName) {
  11.         // TODO Auto-generated method stub
  12.         return new Square(aName + " (created by SquareFactory)");
  13.     }
  14. }
1.e 测试类:请注意这个客户端程序多么简洁,既没有罗嗦的条件判断语句,也无需关心ConcreteProduct和ConcreteCreator的细节(因为这里我用anOperation封装了Product里的两个方法,所以连Product的影子也没看见,当然把Product里方法的具体调用放到客户程序中也是不错的).

点击(此处)折叠或打开

  1. public class Test {
  2.     public static void main(String[] args) {
  3.         ShapeFactory sf1 = new SquareFactory();
  4.         ShapeFactory sf2 = new CircleFactory();
  5.         sf1.anOperation("Shape one");
  6.         sf2.anOperation("Shape two");
  7.     }
  8. }
运行结果如下:
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: 这种方式依靠指定的参数作为标志来创建对应的实例,这是很常见的一种办法,参数化的创建方式克服了Factory Method模式一个最显著的缺陷,就是当具体产品比较多时,我们不得不也建立一系列与之对应的具体构造器. 但是在客户端我们必须指定参数来决定要创建哪一个类.
2.a 我们在第一种方法的基础上进行修改,首先自定义一个的异常,这样当传入不正确的参数时可以得到更明显的报错信息.

点击(此处)折叠或打开

  1. public class NoThisShape extends Exception {
  2.     private static final long serialVersionUID = 1L;

  3.     public NoThisShape(String aName) {
  4.         super(aName);
  5.     }
  6. }
2.b去掉了ShapeFactory的两个子类,改为由ShapeFactory直接负责实例的创建. ShapeFactory自己变成一个具体的创建器,直接用参数化的方法实现factoryMethod返回多种对象.

点击(此处)折叠或打开

  1. public abstract class ShapeFactory {
  2.     private static Shape s;
  3.     private ShapeFactory(){}
  4.     
  5.     static Shape factoryMethod(String aName,String aType) throws NoThisShape {
  6.         if (aType.compareTo("square") == 0) {
  7.             return new Square(aName);
  8.         } else if (aType.compareTo("circle") == 0) {
  9.             return new Circle(aName);
  10.         } else {
  11.             throw new NoThisShape(aType);
  12.         }
  13.     }
  14.     
  15.     static void anOperation(String aName,String aType) throws NoThisShape {
  16.         s = factoryMethod(aName, aType);
  17.         s.draw();
  18.         s.erase();
  19.     }
  20. }
2.c 测试类:这里客户端必须指定参数来决定具体创建哪个类.这个例子里的anOperation是静态函数,可以直接引用.

点击(此处)折叠或打开

  1. public class Test {
  2.     public static void main(String[] args) throws NoThisShape{
  3.         ShapeFactory.anOperation("Shape one","circle");
  4.      ShapeFactory.anOperation("Shape two","square");
  5.      ShapeFactory.anOperation("Shape three", "delta");
  6.     }
  7. }
运行输出:
It will draw a circle.
Exception in thread "main" com.design.factory.NoThisShape: delta
at com.design.factory.ShapeFactory.factoryMethod(ShapeFactory.java:13)
at com.design.factory.ShapeFactory.anOperation(ShapeFactory.java:18)
at com.design.factory.Test.main(Test.java:7)
It will erase a circle.
It will draw a Square.
It will erase a Square.



阅读(1669) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~