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

泡在网上的日子 / 文 发表于2013-05-13 19:38 次阅读 设计模式,抽象工厂模式

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

        产品族:是指位于不同产品等级结构中,功能相关联的产品组成的家族。比如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的源码:

package com.andyidea.patterns.abstractproduct;
/**
 * 抽象产品角色:User接口
 * @author Andy.Chen
 *
 */
public interface IUser {
}

IDepartment.java源码:

package com.andyidea.patterns.abstractproduct;
/**
 * 抽象产品角色:Department接口
 * @author Andy.Chen
 *
 */
public interface IDepartment {
}

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

package com.andyidea.patterns.abstractfactory;
import com.andyidea.patterns.abstractproduct.IDepartment;
import com.andyidea.patterns.abstractproduct.IUser;
/**
 * 抽象工厂角色:工厂接口
 * @author Andy.Chen
 *
 */
public interface IDBFactory {
    public IUser createUser();
    public IDepartment createDepartment();
}

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

OracleOfUser.java源码:

package com.andyidea.patterns.concreteproduct;
import com.andyidea.patterns.abstractproduct.IUser;
/**
 * 具体产品角色:Oracle中的User
 * @author Andy.Chen
 *
 */
public class OracleOfUser implements IUser{
                                                                        
    public OracleOfUser(){
        System.out.println("Oracle工厂:在Oracle中操作User表.");
    }
}

OracleOfDepartment.java源码:

package com.andyidea.patterns.concreteproduct;
import com.andyidea.patterns.abstractproduct.IDepartment;
/**
 * 具体产品角色:Oracle中的Department
 * @author Andy.Chen
 *
 */
public class OracleOfDepartment implements IDepartment{
                                                                
    public OracleOfDepartment(){
        System.out.println("Oracle工厂:在Oracle中操作Department表.");
    }
}

SQLServerOfUser.java源码:

package com.andyidea.patterns.concreteproduct;
import com.andyidea.patterns.abstractproduct.IUser;
/**
 * 具体产品角色:SQL Server中的User
 * @author Andy.Chen
 *
 */
public class SQLServerOfUser implements IUser{
                                                        
    public SQLServerOfUser(){
        System.out.println("SQL Server工厂:在SQL Server中操作User表.");
    }
}

SQLServerOfDepartment.java源码:

package com.andyidea.patterns.concreteproduct;
import com.andyidea.patterns.abstractproduct.IDepartment;
/**
 * 具体产品角色:SQL Server中的Department
 * @author Andy.Chen
 *
 */
public class SQLServerOfDepartment implements IDepartment{
                                              
    public SQLServerOfDepartment(){
        System.out.println("SQL Server工厂:在SQL Server中操作Department表.");
    }
}

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

OracleFactory.java源码:

package com.andyidea.patterns.concretefactory;
import com.andyidea.patterns.abstractfactory.IDBFactory;
import com.andyidea.patterns.abstractproduct.IDepartment;
import com.andyidea.patterns.abstractproduct.IUser;
import com.andyidea.patterns.concreteproduct.OracleOfDepartment;
import com.andyidea.patterns.concreteproduct.OracleOfUser;
/**
 * 具体工厂角色:Oracle工厂
 * @author Andy.Chen
 *
 */
public class OracleFactory implements IDBFactory{
    @Override
    public IUser createUser() {
        return new OracleOfUser();
    }
    @Override
    public IDepartment createDepartment() {
        return new OracleOfDepartment();
    }
}

SQLServerFactory.java源码:

package com.andyidea.patterns.concretefactory;
import com.andyidea.patterns.abstractfactory.IDBFactory;
import com.andyidea.patterns.abstractproduct.IDepartment;
import com.andyidea.patterns.abstractproduct.IUser;
import com.andyidea.patterns.concreteproduct.SQLServerOfDepartment;
import com.andyidea.patterns.concreteproduct.SQLServerOfUser;
/**
 * 具体工厂角色:SQL Server工厂
 * @author Andy.Chen
 *
 */
public class SQLServerFactory implements IDBFactory{
    @Override
    public IUser createUser() {
        return new SQLServerOfUser();
    }
    @Override
    public IDepartment createDepartment() {
        return new SQLServerOfDepartment();
    }
}

3.5 客户端测试类:AbstractFactoryClient.java

package com.andyidea.patterns.client;
import com.andyidea.patterns.abstractproduct.IDepartment;
import com.andyidea.patterns.abstractproduct.IUser;
import com.andyidea.patterns.concretefactory.OracleFactory;
import com.andyidea.patterns.concretefactory.SQLServerFactory;
/**
 * 抽象工厂测试类
 * @author Andy.Chen
 *
 */
public class AbstractFactoryClient {
    public static void main(String[] args) {
                          
        System.out.println("Welcome to Andy.Chen Blog!" +"\n"
                   +"Abstract Factory Patterns." +"\n"
                   +"-------------------------------");
                          
        IUser oracleUser,sqlUser;
        IDepartment oracleDept,sqlDept;
        OracleFactory of = new OracleFactory();
        SQLServerFactory sf = new SQLServerFactory();
                          
        oracleUser = of.createUser();
        oracleDept = of.createDepartment();
        sqlUser = sf.createUser();
        sqlDept = sf.createDepartment();
    }
}

【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(),在一个应用中只需要在初始化的时候出现一次,这就使得改变一个应用的具体工厂变得非常容易,它之需要改变具体工厂即可使用不同的产品配置。
第二,它让具体的创建实例与客户端分离,客户端是通过它们的抽象接口操纵实例,产品的具体类名也被具体工厂的实现分离,不会出现在客户端代码中。


收藏 赞 (0) 踩 (0)
上一篇:相似图片的搜索原理
在谷歌上,你可以用一张图片,搜索互联网上所有与它相似的图片。点击搜索框中照相机的图标。 一个对话框会出现。 你输入网片的网址,或者直接上传图片,Google就会找出与其相似的图片。下面这张图片是美国女演员Alyson Hannigan。 上传后,Google返回如下结
下一篇:字符串匹配的Boyer-Moore算法
上一篇文章,我介绍了 KMP算法 。 但是,它并不是效率最高的算法,实际采用并不多。各种文本编辑器的查找功能(Ctrl+F),大多采用 Boyer-Moore算法 。 Boyer-Moore算法不仅效率高,而且构思巧妙,容易理解。1977年,德克萨斯大学的Robert S. Boyer教授和J S