`
lintomny
  • 浏览: 225717 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

抽象工厂模式

阅读更多
试着总结一下学过的设计模式,就由创建型模式说起吧。

意图
提供一个创建一系列相关活相互依赖对象的接口,而无需指定他们具体的类。
(G4)

任务
假设我们需要进行各种数据库操作,可是我们有很多的选择啊,JDBC,Hibernate,Ibatis等等。本来选择一个就OK了,可是变态的Boss为了炫耀我们的技术如何如何强大,竟说我们能够无成本地在这三个解决方案间切换。这下系统该怎么设计呢?
或许你已经注意到每种解决方案自身都是完备而独立的,不错,这便是解决问题的切入点。提供一套解决方案公有行为的接口,各个解决方案分别实现这些接口,同时建立一个创建各个解决方案的工厂(Factory)。这不就完成任务了吗?哈哈。

首先我们从使用者的角度出发,总结出一套数据库操作的方法,在这里我们称为Service。假设我们只需要一个行为,就是work(),内容是打印出这是来自哪个解决方案。

java 代码
 
  1. /** 
  2.  * 业务类接口  
  3.  */  
  4. public interface Service {  
  5.     /** 
  6.      * 运行业务 
  7.      */  
  8.     void work();  
  9. }  

然后我们根据这个接口分别实现各个解决方案的相应实现。
java 代码
 
  1. /** 
  2.  * A体系中的业务实现
  3.  */  
  4. public class ServiceA implements Service {  
  5.   
  6.     public void work() {  
  7.         System.out.println("这是A体系中业务。");  
  8.     }  
  9. }  

java 代码
 
  1. /** 
  2.  * B体系中的业务实现
  3.  */  
  4. public class ServiceB implements Service {  
  5.    
  6.     public void work() {  
  7.         System.out.println("这是B体系中业务。");  
  8.     }  
  9. }  

大概各位都碰到过需求不断变更,Service不断增加的情况吧。只有一个Service可不够用啊,保不准等会儿Boss就调研回来,需要新增加一个Service2,Service3......ServiceN。如果都写到Service接口里,那可是变成巨无霸了。汉堡包巨无霸我喜欢,代码巨无霸我可就不喜欢了。于是给这些Service建立一个工厂(Factory),以方便地创建各种Service。
那么我们首先来建立一个Factory的接口类。

java 代码
 
  1. /** 
  2.  *  工厂接口
  3.  */  
  4. public interface Factory {  
  5.     /** 
  6.      * 建立创建Service的抽象接口,由各实现的工厂来创建具体的Service 
  7.      */  
  8.      Service createService();  
  9. }  

下面就来实现各个解决方案的工厂。

java 代码
 
  1. /** 
  2.  * 具体的实现工厂A 
  3.  */  
  4. public class FactoryA implements Factory {  
  5.   
  6.     public Service createService() {  
  7.         // 创建本体系中的Service实现  
  8.         return new ServiceA();  
  9.     }  
  10. }  

java 代码
 
  1. /** 
  2.  * 具体的实现工厂B
  3.  */  
  4. public class FactoryB implements Factory {   
  5.     
  6.     public Service createService() {  
  7.         // 创建本体系中的Service实现  
  8.         return new ServiceB();  
  9.     }  
  10. }  

或许各位看官会说这不就是工厂模式嘛,怎么又在前面加上“抽象”二字,难不成是故弄玄虚?非也非也。前头说过了,我们解决问题的切入点是“每种解决方案自身都是完备而独立的”,所以这些具体的各种解决方案的工厂对Consumer也应该是透明的。于是我们给这些工厂(解决方案)加上一个工厂,也就是我们通过这个工厂来生成一整套的解决方案。这个工厂便是我们要说的AbstractFactory

java 代码
 
  1. /** 
  2.  *  抽象工厂
  3.  */  
  4. public  class AbstractFactory {  
  5.     /** 
  6.      * 根据不同的体系要求创建出不同的业务工厂 
  7.      *  
  8.      * @param factoryName 
  9.      * @return 
  10.      */  
  11.     public static AbstractFactory getFactory(String factoryName) {  
  12.         AbstractFactory ist = null;  
  13.         if (factoryName.equalsIgnoreCase("A")) {  
  14.             ist = new FactoryA();  
  15.         } else if (factoryName.equalsIgnoreCase("B")) {  
  16.             ist = new FactoryB();  
  17.         }  
  18.         return ist;  
  19.     }  
  20. }  

本着重构的精神,也为了给点事AbstractFactory做,我便把它和接口Factory合而为一,成为一个抽象类。大概这便是这种设计模式名字的由来吧。呵呵。

java 代码
 
  1. /** 
  2.  *  抽象工厂
  3.  */  
  4. public abstract class AbstractFactory {  
  5.     /** 
  6.      * 根据不同的体系要求创建出不同的业务工厂 
  7.      *  
  8.      * @param factoryName 
  9.      * @return 
  10.      */  
  11.     public static AbstractFactory getFactory(String factoryName) {  
  12.         AbstractFactory ist = null;  
  13.         if (factoryName.equalsIgnoreCase("A")) {  
  14.             ist = new FactoryA();  
  15.         } else if (factoryName.equalsIgnoreCase("B")) {  
  16.             ist = new FactoryB();  
  17.         }  
  18.         return ist;  
  19.     }  
  20.   
  21.     /** 
  22.      * 建立创建Service的抽象接口,由各实现的工厂来创建具体的Service 
  23.      */  
  24.     public abstract Service createService();  
  25. }  

相应的,FactoryA和FactoryB修改为

java 代码
 
  1. public class FactoryA extends AbstractFactory {  
  2.   ......  
  3. }  
  4.   
  5. public class FactoryB extends AbstractFactory {  
  6.   ......  
  7. }  


这样,各种解决方案间的切换便十分容易了。

java 代码
 
  1. /** 
  2.  * 业务的消费者 
  3.  *  
  4.  * @author 聪明的笨蛋 
  5.  * @email lintomny@gmail.com 
  6.  */  
  7. public class Consumer {  
  8.     public void work() {  
  9.         Service service = null;  
  10.   
  11.         // 实现A体系中的业务  
  12.         service = AbstractFactory.getFactory("A").createService();  
  13.         service.work();  
  14.   
  15.         // 实现B体系中的业务  
  16.         service = AbstractFactory.getFactory("B").createService();  
  17.         service.work();  
  18.     }  
  19.   
  20.         //运行  
  21.     public static void main(String[] args) {  
  22.         Consumer csm = new Consumer();  
  23.         csm.work();  
  24.     }  
  25. }  

恩,Mission completed!剩下的就是各个解决方案的实现了,哈哈。那些工作就让,就让.......没有人做,还是我做吧.....谁叫俺是小弟呢。唉~

小结
正如我上面举的这个例子,抽象工厂模式主要适用于需要提供若干种不同实现体系,但又要求有相同处理要求的时候。如Portal技术中,各种Portlet便是不同的体系,但我们在处理Portal的时候都是把他们统一当作Portlet实现,同样这种解决问题的思路可以用在SOA中。这种设计模式大多出现在各个系统进行集成的时候。

题外话
对于上面的抽象工厂中,AbstractFactory依赖于其各子类Factory,这是不合适的。因为这样一来,我们的工程中如果只使用其中一种Factory时,却不得不背上其他用不上的Factory。在这里多做一些改进工作,使用类似于spring中管理bean的方式,对各Factory进行管理。

首先我们需要规定好一种管理格式,在这里以xml为例吧。

xml 代码
 
  1. <beans>  
  2.   <bean id="A" class="com.javaeye.smartfool.FactoryA" />  
  3.   <bean id="B" class="com.javaeye.smartfool.FactoryB" />  
  4. </beans>  

这样,我们可以在AbstractFactory加入一个读配置的方法getXmlClass,通过输入id值来读出其对应的class名。这样,我们的AbstractFactory变成

java 代码
 
  1. public abstract class AbstractFactory {  
  2.   
  3.     // 读取配置文件  
  4.     private static String getXmlClass(String id){  
  5.         ......  
  6.     }  
  7.       
  8.     public static AbstractFactory getFactory(String factoryName) {  
  9.         AbstractFactory ist = null;  
  10.         String className = getXmlClass(factoryName);  
  11.         try {  
  12.             ist = (AbstractFactory) Class.forName(className).newInstance();  
  13.         } catch (Exception e) {  
  14.             e.printStackTrace();  
  15.             ist = null;  
  16.         }   
  17.         return ist;  
  18.     }  
  19.   
  20.     public abstract Service createService();  
  21. }  

这样,就可以解除AbstractFactory对子类的依赖了。

更多的关于此类依赖的设计实践可以参考without ejb这书,上面有很多非常好的思想,绝对能受益非浅。

分享到:
评论
9 楼 lsy 2007-04-29  
挺好的,学习楼主分享,学习java,模式很是重要。
学习中。。。
8 楼 lintomny 2007-04-29  
xj4150 写道
引用
从设计和继承原则来说,我觉得父类不应该依赖子类,如果依赖子类,不容易扩展.
如,我要添加一个新的工厂和新的Service,则还需要修改AbstractFactory,这不符合最终使用工厂模式的目的.


同意


我也同意,补充了关于这方面一个解决方法。由于不属于AbstractFactory这个设计模式本身的内容,就把它作为题外话在原文末端加上了。
7 楼 wandou 2007-04-29  
讲得都不咋地。一看就没有写过复杂的项目。
抽象工厂使用应该是被逼出来的,而不是想像出来的。
如果没有足够的编码经验,最好刻意去运用某种模式。
只要不断消除代码中的重复味道,多写一些复杂一点的项目,一定可以学会抽象工厂。
就这么简单。
6 楼 dovecat 2007-04-29  
模式,知道是这么回事就行了.
5 楼 xj4150 2007-04-29  
引用
从设计和继承原则来说,我觉得父类不应该依赖子类,如果依赖子类,不容易扩展.
如,我要添加一个新的工厂和新的Service,则还需要修改AbstractFactory,这不符合最终使用工厂模式的目的.


同意
4 楼 lintomny 2007-04-16  
spiritfrog 写道
** 
/* 具体的实现工厂A 
*/  
public class FactoryA implements AbstractFactory {  
  
    public Service createService() {  
        // 创建本体系中的Service实现  
        return new ServiceA();  
    }  
}  

这里是不是应该实现Factory 接口啊,后来是去掉Factory,直接继承AbstractFactory了吧?


确实是弄错了,不好意思。原文的代码是我事先写好的最终结果,把extends改回成implements,却忘了把AbstractFactory改回成Factory。已修改。
3 楼 jamesby 2007-04-16  
对于
service = AbstractFactory.getFactory("A").createService(); 

的做法不是很认同,应该更改为
service = new FactoryA().createService();

对于如下代码:
    public static AbstractFactory getFactory(String factoryName) {   
        AbstractFactory ist = null;   
        if (factoryName.equalsIgnoreCase("A")) {   
            ist = new FactoryA();   
        } else if (factoryName.equalsIgnoreCase("B")) {   
            ist = new FactoryB();   
        }   
        return ist;   
    }   

也不是很认同,从设计和继承原则来说,我觉得父类不应该依赖子类,如果依赖子类,不容易扩展.
如,我要添加一个新的工厂和新的Service,则还需要修改AbstractFactory,这不符合最终使用工厂模式的目的.

下面说说我对工厂模式的理解,我觉得应该将工厂方法和抽象工厂合并来谈.
什么时候应该使用工厂方法,什么时候应该使用抽象工厂?
我觉得,当一个产品有多个实现的时候应该考虑抽象工厂,否则应使用工厂方法,对于楼主的例子中的产品就是Service.
虽然很多抽象工厂的例子包含多个产品.但是我觉得选择工厂方法和抽象工厂不应该同产品的种类有任何关系。

下面的例子有多个产品系列,但是属于工厂方法,楼主的例子只有一个产品系列,但是属于抽象工厂。

interface ProductA{}

interface ProductB{}

class ConcreteProductA implements ProductA{}

class ConcreteProductB implements ProductB{}

interface Factory{
   public ProductA createProcuctA();
   public ProductB createProcuctB();
}

class ConcreteFactory implements Factory(){
   public ProductA createProcuctA()
   {
   	return new ConcreteProductA();
   }
   public ProductB createProcuctB()
   {
   	return new createProcuctB();
   }
}

class Test{
   methoda{
      //这里没有考虑工厂需要singleton的情况
      ProductA = new ConcreteFactory().createProcuctA();
      ProductB = new ConcreteFactory().createProcuctB();
   }
}


以上是我的个人理解,望批评指正.
2 楼 hbcui1984 2007-04-16  
spiritfrog 写道
** 
/* 具体的实现工厂A 
*/  
public class FactoryA implements AbstractFactory {  
  
    public Service createService() {  
        // 创建本体系中的Service实现  
        return new ServiceA();  
    }  
}  

这里是不是应该实现Factory 接口啊,后来是去掉Factory,直接继承AbstractFactory了吧?


楼主的代码确实有问题,不过大致思想还是说清楚了
1 楼 spiritfrog 2007-04-16  
** 
/* 具体的实现工厂A 
*/  
public class FactoryA implements AbstractFactory {  
  
    public Service createService() {  
        // 创建本体系中的Service实现  
        return new ServiceA();  
    }  
}  

这里是不是应该实现Factory 接口啊,后来是去掉Factory,直接继承AbstractFactory了吧?

相关推荐

    工厂模式:简单工厂模式、工厂方法模式、抽象工厂模式

    工厂模式分为三种主要类型:简单工厂模式、工厂方法模式和抽象工厂模式。 1. **简单工厂模式** 简单工厂模式是最简单的工厂模式实现,它提供一个静态方法或者类来创建对象,这个类通常被称为“工厂”。用户只需要...

    设计模式-抽象工厂模式(讲解及其实现代码)

    抽象工厂模式是设计模式中的一种创建型模式,它提供了一种创建对象集合的接口,而无需指定具体的类。这种模式允许系统独立于如何创建、组合和表示产品对象的细节进行设计,为产品族(一组相关或相互依赖的对象)提供...

    简单工厂模式-工厂方法模式-抽象工厂模式

    在软件设计模式中,工厂模式是一组非常基础且实用的设计模式,主要分为简单工厂模式、工厂方法模式和抽象工厂模式。这些模式都是为了解决对象创建的问题,通过封装对象的创建过程,使得代码更加灵活,易于扩展和维护...

    抽象工厂模式uml类图

    java设计模式 抽象工厂模式详解 一张图让你彻底明白抽象工厂模式

    工厂方法模式和抽象工厂模式的区别

    工厂方法模式和抽象工厂模式是两种常见的设计模式,它们都属于创建型模式,用于解决对象的创建问题。在软件设计中,这两种模式都是用来隔离对象的创建和使用,以提高系统的灵活性和可扩展性。 首先,工厂方法模式的...

    设计模式 - 抽象工厂模式

    设计模式 - 抽象工厂模式 抽象工厂模式是一种创建型设计模式,它提供了一种方式来创建一组相关或相互依赖的对象,而不需要指定具体的类。该模式允许客户端使用抽象的接口来创建一组相关的产品,而不需要关系实际...

    抽象工厂模式+工厂方法模式+策略模式+类图实现手机加工厂

    本文将探讨三个重要的设计模式:抽象工厂模式、工厂方法模式以及策略模式,并结合一个实际的场景——手机加工厂,来具体阐述它们的应用。 首先,我们来看**抽象工厂模式**。这个模式主要用于创建相关或依赖对象的...

    肯德基:抽象工厂模式

    抽象工厂模式是软件工程中常用的一种创建型设计模式,它的核心思想是为创建一组相关或相互依赖的对象提供一个接口,而不需要指定它们具体的类。在Java中,抽象工厂模式被广泛应用,它有助于整合代码,提高系统的可...

    设计模式--抽象工厂模式实现多数据库连接

    抽象工厂模式是设计模式中的一种创建型模式,它提供了一个创建对象族的接口,而无需指定它们的具体类。在.NET开发中,这种模式常用于实现多数据库连接,比如连接到MySQL、SQL Server或Oracle等不同的数据库系统。...

    抽象工厂模式案例代码

    抽象工厂模式是一种设计模式,属于创建型模式,它提供了一种创建对象族的接口,而无需指定其具体的类。这种模式的关键在于“族”,它表示一系列相关或相互依赖的对象。在不指定具体类的情况下,抽象工厂模式使得...

    C#抽象工厂模式

    抽象工厂模式是设计模式中的一种创建型模式,它提供了一种创建对象族的接口,而无需指定具体的类。在C#编程中,这种模式经常被用于实现跨平台或跨框架的代码,使得代码与具体实现解耦,提高系统的灵活性和可扩展性。...

    抽象工厂模式简单小例子

    ### 抽象工厂模式简介与应用实例 #### 一、抽象工厂模式定义 抽象工厂模式是一种创建型设计模式,它能够让我们从一个公共接口中创建一系列相关或相互依赖的对象,而无需指定它们的具体类。该模式的核心在于提供了...

    设计模式-抽象工厂模式

    抽象工厂模式是设计模式中的一种创建型模式,它提供了一种创建对象族的接口,而无需指定其具体的类。这种模式的关键在于“族”,即一系列相关的对象。在抽象工厂模式中,我们创建一个抽象工厂接口,然后为每一种具体...

    简单工厂模式、工厂模式、抽象工厂模式案例(C++实现)

    在这个压缩包中,包含了三种工厂模式的C++实现:简单工厂模式、工厂方法模式以及抽象工厂模式。让我们一一探讨这些模式。 1. 简单工厂模式: 简单工厂模式是一种静态工厂方法,它提供一个公共的工厂类来创建对象。...

    抽象工厂模式+反射技术(抽象工厂模式+简单工厂模式)

    抽象工厂模式是设计模式中的一种,它提供了一个创建一系列相关或相互依赖对象的接口,而无需指定它们的具体类。在软件工程中,当系统需要在运行时选择不同的产品族时,或者想要隔离具体产品的实现细节时,抽象工厂...

    Android抽象工厂模式demo

    抽象工厂模式是设计模式中的一种结构型模式,它提供了一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。在Android开发中,这种模式尤其有用,因为Android平台有多种设备,每种设备可能有不同的UI...

    java设计模式-抽象工厂模式

    抽象工厂模式是设计模式中的一种,它属于创建型模式,主要解决的是当系统有多个产品族,而每个产品族又有多个具体产品时,如何组织代码的问题。在Java中,抽象工厂模式提供了一种创建对象组的方式,使得这些对象属于...

    C#抽象工厂模式案例代码

    抽象工厂模式是一种面向对象的设计模式,它提供了一个创建一系列相关或相互依赖对象的接口,而无需指定它们的具体类。在C#中,这种模式经常用于软件工程中的框架设计,允许系统独立于具体产品的实现进行扩展和修改。...

    工厂方法模式和抽象工厂模式

    在软件设计模式中,工厂方法模式(Factory Method Pattern)和抽象工厂模式(Abstract Factory Pattern)是两种常用的创建型设计模式,它们都属于“工厂”家族,但有着不同的应用场景和目标。 工厂方法模式的核心...

    抽象工厂模式实现计算器

    抽象工厂模式是一种创建型设计模式,它提供了一种创建对象族的方法,而无需指定它们的具体类。在计算器的实现中,这个模式可以帮助我们构建不同类型的计算器,比如简单计算器、科学计算器等,而无需修改现有代码。 ...

Global site tag (gtag.js) - Google Analytics