`
derekop
  • 浏览: 22891 次
  • 性别: Icon_minigender_1
  • 来自: 天津
社区版块
存档分类
最新评论

在JAVA中应用设计模式FactoryMethod

    博客分类:
  • java
阅读更多

 FactoryMethod是一种创建性模式,它定义了一个创建对象的接口,但是却让子类来决定具体实例化哪一个类.当一个类无法预料要创建哪种类的对象或是一个类需要由子类来指定创建的对象时我们就需要用到Factory Method 模式了.简单说来,Factory Method可以根据不同的条件产生不同的实例,当然这些不同的实例通常是属于相同的类型,具有共同的父类.Factory Method把创建这些实例的具体过程封装起来了,简化了客户端的应用,也改善了程序的扩展性,使得将来可以做最小的改动就可以加入新的待创建的类. 通常我们将Factory Method作为一种标准的创建对象的方法,当发现需要更多的灵活性的时候,就开始考虑向其它创建型模式转化:

  图1是Factory Method 模式的结构图,这里提供了一些术语,让我们可以进行更方便的描述:

  Product: 需要创建的产品的抽象类.

  ConcreteProduct: Product的子类,一系列具体的产品.

  Creator: 抽象创建器接口,声明返回Product类型对象的Factory Method.

  ConcreteCreator: 具体的创建器,重写Creator中的Factory Method,返回ConcreteProduct类型的实例.
 
图1: Factory Method 模式结构

 

 

 由此可以清楚的看出这样的平行对应关系: Product <====> Creator ; ConreteProduct <====> ConreteCreator

  抽象产品对应抽象创建器,具体产品对应具体创建器.这样做的好处是什么呢?为什么我们不直接用具体的产品和具体的创建器完成需求呢?实际上我们也可以这样做.但通过Factory Method模式来完成,客户(client)只需引用抽象的Product和Creater,对具体的ConcreteProduct和 ConcreteCreator可以毫不关心,这样做我们可以获得额外的好处:

  首先客户端可以统一从抽象创建器获取产生的实例,Creator的作用将client和产品创建过程分离开来,客户不用操心返回的是那一个具体的产品,也不用关心这些产品是如何创建的.同时,ConcreteProduct也被隐藏在Product后面,ConreteProduct继承了Product的所有属性,并实现了 Product中定义的抽象方法,按照Java中的对象造型(cast)原则,通过ConcreteCreator产生的ConcreteProduct 可以自动的上溯造型成Product.这样一来,实质内容不同的ConcreteProduct就可以在形式上统一为Product,通过Creator 提供给client来访问.

  其次,当我们添加一个新的ConcreteCreator时,由于Creator所提供的接口不变,客户端程序不会有丝毫的改动,不会带来动一发而牵全身的灾难, 这就是良好封装性的体现.但如果直接用ConcreteProduct和ConcreteCreator两个类是无论如何也做不到这点的. 优良的面向对象设计鼓励使用封装(encapsulation)和委托(delegation),而Factory Method模式就是使用了封装和委托的典型例子,这里封装是通过抽象创建器Creator来体现的,而委托则是通过抽象创建器把创建对象的责任完全交给具体创建器ConcreteCreator来体现的.

  现在,请再回头看看基本概念中的那段话,开始也许觉得生涩难懂,现在是不是已经明朗化了很多.

  下面让我们看看在 Java 中如何实现Factory Method模式,进一步加深对它的认识.

 

先说明一点,用Factory Method模式创建对象并不一定会让我们的代码更短,实事上往往更长,我们也使用了更多的类,真正的目的在于这样可以灵活的,有弹性的创建不确定的对象.而且,代码的可重用性提高了,客户端的应用简化了,客户程序的代码会大大减少,变的更具可读性.

  标准实现: 这里我采用Bruce Eckel 用来描述OO思想的经典例子 Shape.这样大家会比较熟悉一些.我完全按照图1中所定义的结构写了下面的一段演示代码.这段代码的作用是创建不同的Shape实例,每个实例完成两个操作:draw和erase.具体的创建过程委托?oShapeFactory来完成.

  1.a 首先定义一个抽象类Shape,定义两个抽象的方法.

 

  abstract class Shape {
   // 勾画shape
   public abstract void draw();
   // 擦去 shape
   public abstract void erase();
   public String name;

   public Shape(String aName){

   name = aName;
   }
   }

 

   1.b 定义 Shape的两个子类: Circle, Square,实现Shape中定义的抽象方法

 // 圆形子类
   class Circle extends Shape {
   public void draw() {
   System.out.println("It will draw a circle.");
   }

   public void erase() {
   System.out.println("It will erase a circle.");

   }

   // 构造函数
   public Circle(String aName){

   super(aName);

   }
   }
   // 方形子类
   class Square extends Shape {
   public void draw() {
   System.out.println("It will draw a square.");
   }

   public void erase() {
   System.out.println("It will erase a square.");
   }
   // 构造函数
   public Square(String aName){

   super(aName);
   }
   }

  1.c 定义抽象的创建器,anOperation调用factoryMethod创建一个对象,并对该对象进行一系列操作.

 abstract class ShapeFactory {
   protected abstract Shape factoryMethod(String aName);
   // 在anOperation中定义Shape的一系列行为
   public void anOperation(String aName){

   Shape s = factoryMethod(aName);

   System.out.println("The current shape is: " + s.name);
   s.draw();

   s.erase();
   }
   }

  1.d 定义与circle和square相对应的两个具体创建器CircleFactory,SquareFactory,实现父类的methodFactory方法

 // 定义返回 circle 实例的 CircleFactory
   class CircleFactory extends ShapeFactory {
   // 重载factoryMethod方法,返回Circle对象
   protected Shape factoryMethod(String aName) {
   return new Circle(aName + " (created by CircleFactory)");

   }
   }
   // 定义返回 Square 实例的 SquareFactory
   class SquareFactory extends ShapeFactory {
   // 重载factoryMethod方法,返回Square对象

   protected Shape factoryMethod(String aName) {
   return new Square(aName + " (created by SquareFactory)");
   }
   }

  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");

   }

   }

 

  运行结果如下:

  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");

   }

   }

 

 动态装载机制:

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

  我们得到一个Shape的子类s,但不知道具体是那个子类,就可以利用Class类自带的方法newInstance()得到实例

  return (Shape)s.getClass().newInstance();

  

 

转自 http://tech.it168.com/a2009/0221/266/000000266213_1.shtml

分享到:
评论

相关推荐

    Java常用设计模式(SingleTon、FactoryMethod、AbstractFactory)

    Java设计模式是面向对象编程...在阅读《Chapter1___Java常用设计模式(SingleTon、FactoryMethod、AbstractFactory)》的相关资料时,你可以更深入地学习这些模式的细节,包括适用场景、优缺点以及如何在实际项目中实现。

    在Java中应用设计模式-FactoryMethod

    在设计模式中,FactoryMethod也是比较简单的一个,但应用非常广泛,EJB,RMI,COM,CORBA,Swing中都可以看到此模式的影子,它是最重要的模式之一.在很多地方我们都会看到xxxFactory这样命名的类,那么,什么是FactoryMethod,...

    设计模式-Java语言中的应用(pdf)

    在Java中,设计模式的应用广泛且深入。例如,单例模式在系统配置、线程池等场景下极为常见,它确保一个类只有一个实例,并提供全局访问点。工厂方法模式用于创建对象,允许推迟实例化到子类,增强了代码的灵活性。...

    JAVA设计模式在JDK中的应用

    ### JAVA设计模式在JDK中的应用 #### 一、引言 在软件开发过程中,设计模式作为一套被广泛接受的解决方案,能够帮助开发者解决常见的设计问题。Java作为一门流行的编程语言,其标准库(JDK)中巧妙地融入了多种设计...

    设计模式 在java语言中的应用

    设计模式是软件工程中的一种最佳实践,它是在特定上下文中解决常见问题的模板。在Java编程语言中,设计模式的应用可以极大地提升代码的可读性、可维护...因此,深入理解和应用设计模式是每个Java开发者必备的技能之一。

    JAVA23中设计模式

    通过学习和应用这些设计模式,《JAVA23中设计模式》能够极大地提升开发者的编程技能,并帮助他们在实际工作中解决具体的问题。无论你是初学者还是有经验的开发者,熟悉这些模式都将对你的职业生涯大有裨益。

    java的设计模式 《设计模式-java语言中的应用.pdf》

    《设计模式——Java语言中的应用》这本书深入探讨了如何在Java中有效地运用这些模式。 1. **单例模式**:确保一个类只有一个实例,并提供全局访问点。在Java中,可以通过双重检查锁定(Double-Checked Locking)或...

    设计模式_java语言中的应用

    本文将深入探讨在Java语言中常用的一些设计模式,包括Iterator(迭代器)、Adapter(适配器)、Template Method(模板方法)、Factory Method(工厂方法)以及Abstract Factory(抽象工厂)。这些模式在实际开发中...

    JAVA21种设计模式

    在软件开发中,设计模式是一种被广泛接受的解决方案,用于解决常见的设计问题。这些模式是经验丰富的开发者在实践中总结出来的,它们为复杂问题提供了一种标准化的方法。Java的21种设计模式涵盖了创建型、结构型和...

    Java设计模式刘伟书本中模拟考试答案

    在《Java设计模式》这本书的模拟试题及其参考答案中,涉及了多条设计模式的知识点,以及它们的应用场景和实现方法。现在将这些知识点详细地解释如下: 1. 开闭原则(Open-Closed Principle, OCP): 开闭原则是面向...

    JAVA 23种设计模式(全).Design Pattern_Java模式

    在Java中,面向对象特性如封装、继承和多态为设计模式提供了坚实的基础。例如,装饰模式通过组合而非继承来动态地给对象添加新的行为或职责,这避免了类爆炸问题;而策略模式则利用接口和实现类的多态性,使算法的...

    设计模式:Java语言中的应用.zip

    在Java语言中,设计模式的应用广泛且至关重要,因为它们能帮助开发者遵循良好的编程原则,如开闭原则、单一职责原则、依赖倒置原则等。 首先,我们来看一些基本的设计模式类型: 1. 创建型模式:这类模式主要处理...

    CBF4LIFE的《设计模式讲解JAVA》

    在《设计模式讲解JAVA》一书中,作者CBF4LIFE以《三国演义》中刘备娶亲的典故为背景,通过生动的故事和代码示例,深入浅出地讲解了各种设计模式的概念、应用和实现。下面将详细探讨书中的关键知识点。 首先,书中...

    Java 企业设计模式

    Java企业设计模式是软件开发领域中的重要组成部分,它是一套经过实践验证的解决方案,用于解决在Java环境中构建大型、复杂企业应用时常见的问题。这些模式是经验丰富的开发者们通过不断尝试和总结,形成的最佳实践,...

    java软件构架设计模式.rar

    Java软件架构设计模式是软件开发领域中的重要主题,它涉及到如何高效、可扩展且易于维护地构建大型Java应用程序。设计模式是一种在特定上下文中解决常见问题的最佳实践模板,它们是经验丰富的开发者们智慧的结晶,已...

    《java设计模式》课后习题模拟试题解答——刘伟.zip

    Java设计模式是软件工程中的一种最佳实践,它总结了在特定场景下解决常见问题的经验,为程序员提供了可重用的解决方案。本资料“《java设计模式》课后习题模拟试题解答——刘伟.zip”主要涵盖了Java设计模式的学习与...

    《Java设计模式》课后答案-刘伟.rar

    在Java开发中,掌握设计模式对于提升编程技能和解决复杂问题具有关键作用。 本书涵盖了23种经典的GOF(GoF,Gang of Four)设计模式,包括创建型、结构型和行为型三大类。创建型设计模式如单例(Singleton)、工厂...

    Java 中的设计模式 - jdon

    《Java中的设计模式 - jdon》是一本深入探讨Java编程中设计模式的电子书,它主要聚焦于如何在实际开发中应用和理解这些经典的设计原则和模式。设计模式是软件工程中的一种最佳实践,它总结了在特定上下文中解决常见...

    Java设计模式及案例1

    Java设计模式是软件开发中的重要概念,它是一种在特定情境下解决问题的经验总结,可以提高代码的可重用性、可维护性和...无论你是初学者还是经验丰富的开发者,深入理解和熟练应用设计模式都将极大地提升你的编程水平。

Global site tag (gtag.js) - Google Analytics