在學習抽象工廠具體實例之前,應(yīng)該明白兩個重要的概念:產(chǎn)品族和產(chǎn)品等級。
產(chǎn)品族:是指位于不同產(chǎn)品等級結(jié)構(gòu)中,功能相關(guān)聯(lián)的產(chǎn)品組成的家族。比如AMD的CPU和ADM芯片的主板,組成一個家族。Intel的CPU和Intel芯片的主板,又組成一個家族。而這兩個家族都來自于兩個產(chǎn)品等級:CPU,主板。一個等級結(jié)構(gòu)是由相同的結(jié)構(gòu)的產(chǎn)品組成,示意圖如下:
理解這個產(chǎn)品結(jié)構(gòu)是理解抽象工廠模式的關(guān)鍵所在,從上圖可以看出,抽象工廠模式的每個工廠創(chuàng)造出來的都是一族產(chǎn)品,而不是一個或者一組。組是可以隨意組合的!其實工廠方法模式和抽象工廠模式就這點點差別。
【1】基本概念
抽象工廠模式是提供一個創(chuàng)建一系列相關(guān)或相互依賴對象的接口,而無需指定它們具體類。
【2】簡單分析
我們先看一下抽象工廠模式的UML結(jié)構(gòu)圖:
上圖是 Abstract Factory 模式結(jié)構(gòu)圖,讓我們可以進行更加方便的描述:
- AbstractProduct: 抽象產(chǎn)品,它們都有可能有兩種不同的實現(xiàn)。
- ConcreteProduct:包括ProductA和ProductB, 對兩個抽象產(chǎn)品的具體分類的實現(xiàn)。
- AbstractFactory: 抽象工廠接口,它里面應(yīng)該包含所有的產(chǎn)品創(chuàng)建的抽象方法。
- ConcreteFactory: 包括ConcreteFactoryA和ConcreteFactoryB,具體的工廠,創(chuàng)建具有特定實現(xiàn)的產(chǎn)品對象。
背景:用一個分別對不同數(shù)據(jù)庫(Oracle 或 SQL Server)中表( User 和 Department )的操作的實例來展示該設(shè)計模式。先看下代碼的結(jié)構(gòu)圖:
3.1 首先定義兩個抽象的產(chǎn)品類:IUser.java 和 IDepartment.java。
IUser.java的源碼:
- package com.andyidea.patterns.abstractproduct;
- /**
- * 抽象產(chǎn)品角色:User接口
- * @author Andy.Chen
- *
- */
- public interface IUser {
- }
- package com.andyidea.patterns.abstractproduct;
- /**
- * 抽象產(chǎn)品角色:Department接口
- * @author Andy.Chen
- *
- */
- public interface IDepartment {
- }
- 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();
- }
OracleOfUser.java源碼:
- package com.andyidea.patterns.concreteproduct;
- import com.andyidea.patterns.abstractproduct.IUser;
- /**
- * 具體產(chǎn)品角色:Oracle中的User
- * @author Andy.Chen
- *
- */
- public class OracleOfUser implements IUser{
- public OracleOfUser(){
- System.out.println("Oracle工廠:在Oracle中操作User表.");
- }
- }
- package com.andyidea.patterns.concreteproduct;
- import com.andyidea.patterns.abstractproduct.IDepartment;
- /**
- * 具體產(chǎn)品角色:Oracle中的Department
- * @author Andy.Chen
- *
- */
- public class OracleOfDepartment implements IDepartment{
- public OracleOfDepartment(){
- System.out.println("Oracle工廠:在Oracle中操作Department表.");
- }
- }
- package com.andyidea.patterns.concreteproduct;
- import com.andyidea.patterns.abstractproduct.IUser;
- /**
- * 具體產(chǎn)品角色:SQL Server中的User
- * @author Andy.Chen
- *
- */
- public class SQLServerOfUser implements IUser{
- public SQLServerOfUser(){
- System.out.println("SQL Server工廠:在SQL Server中操作User表.");
- }
- }
- package com.andyidea.patterns.concreteproduct;
- import com.andyidea.patterns.abstractproduct.IDepartment;
- /**
- * 具體產(chǎn)品角色:SQL Server中的Department
- * @author Andy.Chen
- *
- */
- public class SQLServerOfDepartment implements IDepartment{
- public SQLServerOfDepartment(){
- System.out.println("SQL Server工廠:在SQL Server中操作Department表.");
- }
- }
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();
- }
- }
- 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();
- }
- }
- 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();
- }
- }
- Welcome to Andy.Chen Blog!
- Abstract Factory Patterns.
- -------------------------------
- Oracle工廠:在Oracle中操作User表.
- Oracle工廠:在Oracle中操作Department表.
- SQL Server工廠:在SQL Server中操作User表.
- SQL Server工廠:在SQL Server中操作Department表.
抽象工廠模式優(yōu)點:
第一,易于交換產(chǎn)品系列,由于具體工廠類,例如IDBFactory factory = new OracleFactory(),在一個應(yīng)用中只需要在初始化的時候出現(xiàn)一次,這就使得改變一個應(yīng)用的具體工廠變得非常容易,它之需要改變具體工廠即可使用不同的產(chǎn)品配置。
第二,它讓具體的創(chuàng)建實例與客戶端分離,客戶端是通過它們的抽象接口操縱實例,產(chǎn)品的具體類名也被具體工廠的實現(xiàn)分離,不會出現(xiàn)在客戶端代碼中。
http://blog.csdn.net/cjjky/article/details/7346893