微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

设计模式之六 --- 抽象工厂模式(Abstract Factory)

http://www.voidcn.com/article/p-mcofosod-ey.html

 

每个模式都是针对一定问题的解决方案。抽象工厂模式面对的问题是多产品等级结构的系统设计。
         在学习抽象工厂具体实例之前,应该明白两个重要的概念:产品族和产品等级。

         产品族:是指位于不同产品等级结构中,功能相关联的产品组成的家族。比如AMD的cpu和ADM芯片的主板,组成一个家族。Intel的cpu和Intel芯片的主板,又组成一个家族。而这两个家族都来自于两个产品等级:cpu,主板。一个等级结构是由相同的结构的产品组成,示意图如下:


 理解这个产品结构是理解抽象工厂模式的关键所在,从上图可以看出,抽象工厂模式的每个工厂创造出来的都是一族产品,而不是一个或者一组。组是可以随意组合的!其实工厂方法模式和抽象工厂模式就这点点差别。

【1】基本概念

         抽象工厂模式是提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体类。

【2】简单分析

我们先看一下抽象工厂模式的UML结构图:

上图是 Abstract Factory 模式结构图,让我们可以进行更加方便的描述:

  1. AbstractProduct: 抽象产品,它们都有可能有两种不同的实现。
  2. ConcreteProduct:包括ProductA和ProductB, 对两个抽象产品的具体分类的实现。
  3. AbstractFactory: 抽象工厂接口,它里面应该包含所有的产品创建的抽象方法
  4. ConcreteFactory: 包括ConcreteFactoryA和ConcreteFactoryB,具体的工厂,创建具有特定实现的产品对象。

【3】如何用java语言来实现该模式
背景:用一个分别对不同数据库(Oracle 或 sql Server)中表( User 和 Department )的操作的实例来展示该设计模式。先看下代码的结构图:


3.1 首先定义两个抽象的产品类:IUser.java 和 IDepartment.java。

IUser.java的源码:

  1. package com.andyidea.patterns.abstractproduct;  
  2.   
  3. /**  
  4.  * 抽象产品角色:User接口  
  5.  * @author Andy.Chen  
  6.  *  
  7.  */  
  8. public interface IUser {  
  9.   
  10. }  

IDepartment.java源码:

  1. package com.andyidea.patterns.abstractproduct;  
  2.   
  3. /**  
  4.  * 抽象产品角色:Department接口  
  5.  * @author Andy.Chen  
  6.  *  
  7.  */  
  8. public interface IDepartment {  
  9.   
  10. }  

3.2 定义抽象工厂类:IDBFactory.java

  1. package com.andyidea.patterns.abstractfactory;  
  2.   
  3. import com.andyidea.patterns.abstractproduct.IDepartment;  
  4. import com.andyidea.patterns.abstractproduct.IUser;  
  5.   
  6. /**  
  7.  * 抽象工厂角色:工厂接口  
  8.  * @author Andy.Chen  
  9.  *  
  10.  */  
  11. public interface IDBFactory {  
  12.   
  13.     public IUser createuser();  
  14.     public IDepartment createDepartment();  
  15. }  

3.3创建具体产品角色类:OracleOfUser.java;OracleOfDepartment.java;sqlServerOfUser.java;sqlServerOfDepartment.java。分别继承IUser.java和IDepartment.java。

OracleOfUser.java源码:

  1. package com.andyidea.patterns.concreteproduct;  
  2.   
  3. import com.andyidea.patterns.abstractproduct.IUser;  
  4.   
  5. /**  
  6.  * 具体产品角色:Oracle中的User  
  7.  * @author Andy.Chen  
  8.  *  
  9.  */  
  10. public class OracleOfUser implements IUser{  
  11.       
  12.     public OracleOfUser(){  
  13.         System.out.println("Oracle工厂:在Oracle中操作User表.");  
  14.     }  
  15.   
  16. }  

OracleOfDepartment.java源码:

  1. package com.andyidea.patterns.concreteproduct;  
  2.   
  3. import com.andyidea.patterns.abstractproduct.IDepartment;  
  4.   
  5. /**  
  6.  * 具体产品角色:Oracle中的Department  
  7.  * @author Andy.Chen  
  8.  *  
  9.  */  
  10. public class OracleOfDepartment implements IDepartment{  
  11.       
  12.     public OracleOfDepartment(){  
  13.         System.out.println("Oracle工厂:在Oracle中操作Department表.");  
  14.     }  
  15.   
  16. }  

sqlServerOfUser.java源码:

  1. package com.andyidea.patterns.concreteproduct;  
  2.   
  3. import com.andyidea.patterns.abstractproduct.IUser;  
  4.   
  5. /**  
  6.  * 具体产品角色:sql Server中的User  
  7.  * @author Andy.Chen  
  8.  *  
  9.  */  
  10. public class sqlServerOfUser implements IUser{  
  11.       
  12.     public sqlServerOfUser(){  
  13.         System.out.println("sql Server工厂:在sql Server中操作User表.");  
  14.     }  
  15.   
  16. }  

sqlServerOfDepartment.java源码:

  1. package com.andyidea.patterns.concreteproduct;  
  2.   
  3. import com.andyidea.patterns.abstractproduct.IDepartment;  
  4.   
  5. /**  
  6.  * 具体产品角色:sql Server中的Department  
  7.  * @author Andy.Chen  
  8.  *  
  9.  */  
  10. public class sqlServerOfDepartment implements IDepartment{  
  11.       
  12.     public sqlServerOfDepartment(){  
  13.         System.out.println("sql Server工厂:在sql Server中操作Department表.");  
  14.     }  
  15.   
  16. }  

3.4 创建具体工厂类:OracleFactory.java和sqlServerFactory.java。

OracleFactory.java源码:

  1. package com.andyidea.patterns.concretefactory;  
  2.   
  3. import com.andyidea.patterns.abstractfactory.IDBFactory;  
  4. import com.andyidea.patterns.abstractproduct.IDepartment;  
  5. import com.andyidea.patterns.abstractproduct.IUser;  
  6. import com.andyidea.patterns.concreteproduct.OracleOfDepartment;  
  7. import com.andyidea.patterns.concreteproduct.OracleOfUser;  
  8.   
  9. /**  
  10.  * 具体工厂角色:Oracle工厂  
  11.  * @author Andy.Chen  
  12.  *  
  13.  */  
  14. public class OracleFactory implements IDBFactory{  
  15.   
  16.     @Override  
  17.     public IUser createuser() {  
  18.         return new OracleOfUser();  
  19.     }  
  20.   
  21.     @Override  
  22.     public IDepartment createDepartment() {  
  23.         return new OracleOfDepartment();  
  24.     }  
  25.   
  26. }  

sqlServerFactory.java源码:

  1. package com.andyidea.patterns.concretefactory;  
  2.   
  3. import com.andyidea.patterns.abstractfactory.IDBFactory;  
  4. import com.andyidea.patterns.abstractproduct.IDepartment;  
  5. import com.andyidea.patterns.abstractproduct.IUser;  
  6. import com.andyidea.patterns.concreteproduct.sqlServerOfDepartment;  
  7. import com.andyidea.patterns.concreteproduct.sqlServerOfUser;  
  8.   
  9. /**  
  10.  * 具体工厂角色:sql Server工厂  
  11.  * @author Andy.Chen  
  12.  *  
  13.  */  
  14. public class sqlServerFactory implements IDBFactory{  
  15.   
  16.     @Override  
  17.     public IUser createuser() {  
  18.         return new sqlServerOfUser();  
  19.     }  
  20.   
  21.     @Override  
  22.     public IDepartment createDepartment() {  
  23.         return new sqlServerOfDepartment();  
  24.     }  
  25.   
  26. }  

3.5 客户端测试类:AbstractFactoryClient.java

  1. package com.andyidea.patterns.client;  
  2.   
  3. import com.andyidea.patterns.abstractproduct.IDepartment;  
  4. import com.andyidea.patterns.abstractproduct.IUser;  
  5. import com.andyidea.patterns.concretefactory.OracleFactory;  
  6. import com.andyidea.patterns.concretefactory.sqlServerFactory;  
  7.   
  8. /**  
  9.  * 抽象工厂测试类  
  10.  * @author Andy.Chen  
  11.  *  
  12.  */  
  13. public class AbstractFactoryClient {  
  14.   
  15.     public static void main(String[] args) {  
  16.           
  17.         System.out.println("Welcome to Andy.Chen Blog!" +"\n"   
  18.                    +"Abstract Factory Patterns." +"\n"  
  19.                    +"-------------------------------");  
  20.           
  21.         IUser oracleUser,sqlUser;  
  22.         IDepartment oracleDept,sqlDept;  
  23.         OracleFactory of = new OracleFactory();  
  24.         sqlServerFactory sf = new sqlServerFactory();  
  25.           
  26.         oracleUser = of.createuser();  
  27.         oracleDept = of.createDepartment();  
  28.         sqlUser = sf.createuser();  
  29.         sqlDept = sf.createDepartment();  
  30.     }  
  31. }  

【4】程序运行结果:

  1. Welcome to Andy.Chen Blog!  
  2. Abstract Factory Patterns.  
  3. -------------------------------  
  4. Oracle工厂:在Oracle中操作User表.  
  5. Oracle工厂:在Oracle中操作Department表.  
  6. sql Server工厂:在sql Server中操作User表.  
  7. sql Server工厂:在sql Server中操作Department表.  

【5】总结

抽象工厂模式优点:

第一,易于交换产品系列,由于具体工厂类,例如IDBFactory factory = new OracleFactory(),在一个应用中只需要在初始化的时候出现一次,这就使得改变一个应用的具体工厂变得非常容易,它之需要改变具体工厂即可使用不同的产品配置。 第二,它让具体的创建实例与客户端分离,客户端是通过它们的抽象接口操纵实例,产品的具体类名也被具体工厂的实现分离,不会出现在客户端代码中。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐