设计模式之抽象工厂模式

抽象工厂模式(Abstract Factory Pattern)是一种比较常用的模式,其定义如下:

Provide an interface for creating families of related or dependent objects without specifying their concrete classes。

为创建一组相关或相互依赖的对象提供一个接口,而且无需指定它们的具体类。


举一个电脑产品的例子吧:

IBM,Dell都是著名的计算机生产厂家,他们采用的主板、硬盘及CPU是不相同的,但是配件间、主板与CPU一定要相互兼容,例如下面例子中的微星MSIK7N2G配AMD的CPU;微星MSI865PE配Intel的CPU。

如图中所示,ComputerFactory是抽象工厂,Dell和IBM是生产产品的工厂;CPU、HardDisk、MainBoard是抽象产品,CPU的型号又分许多种。

uml关系图如下:

 

具体实现见代码:

首先,定义CPU的接口:

public interface CPU {

String getCPU();

}

定义AMD类,实现CPU接口:

public class AMD implements CPU {

@Override

public String getCPU() {

return  "Athlon XP 2008+";

}

}

定义Intel类,实现CPU接口:

public class Intel implements CPU{

@Override

public String getCPU() {

return "奔腾4 3.2C";

}

}

定义硬盘接口:

public interface HardDisk {

String getSize();

}

定义Maxtor类,实现硬盘接口:

public class Maxtor implements HardDisk{

@Override

public String getSize() {

// TODO Auto-generated method stub

return "MaXLine Plus II 200G";

}

}

定义WestDigit,实现硬盘接口:

public class WestDigit implements HardDisk{

@Override

public String getSize() {

return "WD2500JD 250G";

}

}

定义主板的接口,包含参数为CPU的公共方法Attach():

public interface MainBoard {

 void Attach(CPU cpu) throws Exception;

}

主板微星MSI865PE,支持IntelCPU

public class MSI865PE implements MainBoard{

 

@Override

public void Attach(CPU cpu) throws Exception {

 if(cpu.getClass ().toString ().endsWith("Intel")){

            System.out.println("MSI865PE");

        }

         else{

            throw new Exception("主板MSI865PE只能配IntelCPU");

        }

}

}

主板微星MSIK7N2G,支持AMDCPU

public class MSIK7N2G implements MainBoard {

 

@Override

public void Attach(CPU cpu) throws Exception {

if(cpu.getClass ().toString ().endsWith("AMD")){

            System.out.println("MSIK7N2G");

        }

         else{

            throw new Exception("主板MSIK7N2G只能配AMDCPU");

        }

}

 

}

定义抽象电脑工厂类:

public abstract class ComputerFactory {

CPU cpu;

HardDisk hd;

MainBoard mb;

 

public void show() {

try {

System.out.println(this.getClass().getName().toString() + ("生产的电脑配置"));

System.out.println("CPU:" + cpu.getCPU());

System.out.println("HardDisk:" + hd.getSize());

System.out.print("MainBoard:");

mb.Attach(cpu);

} catch (Exception e) {

System.err.println(e.getMessage());

}

}

}

抽象电脑工厂类派生类IBM,定义其返回的系列配件产品:

public class IBM extends ComputerFactory {

 

public IBM() {

cpu = new Intel();

hd = new WestDigit();

mb = new MSI865PE();

}

 

}

抽象电脑工厂类派生类Dell,定义其返回的系列配件产品:

public class Dell extends ComputerFactory {

public Dell(){

cpu = new AMD();

        hd = new Maxtor();

        mb = new MSIK7N2G();

}

}

客户程序调用:

public class Client {

public static void main(String[] args) {

IBM ibm = new IBM();

ibm.show();

Dell dell = new Dell();

dell.show();

}

}

输出结果为:

Computerworld.IBM生产的电脑配置

CPU:奔腾4 3.2C

HardDisk:WD2500JD 250G

MainBoard:MSI865PE

Computerworld.Dell生产的电脑配置

CPU:Athlon XP 2800+

HardDisk:MaXLine Plus II 200G

MainBoard:MSIK7N2G

抽象工厂模式的缺点

     抽象工厂模式的最大缺点就是产品族扩展非常困难,为什么这么说呢?我们以通用代码为例,如果要增加一个产品C,也就是说有产品家族由原来的2个,增加到3 个,看看我们的程序有多大改动吧!抽象类AbstractCreator要增加一个方法createProductC(),然后,两个实现类都要修改,想 想看,这在项目中的话,还这么让人活!严重违反了开闭原则,而且我们一直说明抽象类和接口是一个契约,改变契约,所有与契约有关系的代码都要修改,这段代 码叫什么?叫“有毒代码”,——只要这段代码有关系,就可能产生侵害的危险!

最佳实践

     一个模式在什么情况下才能够使用,是我刚开始比较困惑的地方,抽象工厂模式是一个简单的模式,使用的场景非常多,在软件产品开发过程中,涉及到不同操 作系统的时候,都可以考虑使用抽象工厂模式,例如一个应用,需要在三个不同平台上运行:Windows、Linux、Android(Google发布的 智能终端操作系统)上运行,你会怎么设计?分别设计三套不同的应用?非也非也,通过抽象工厂模式屏蔽掉操作系统对应用的影响。三个不同操作系统上的软件功 能、应用逻辑、UI都应该是非常类似,唯一不同的是调用不同的工厂方法,由不同的产品类去处理与操作系统交互的信息。

与工厂模式区别:
工厂模式只有一个抽象产品类,而抽象工厂模式有多个。  
工厂模式的具体工厂类只能创建一个具体产品类的实例,而抽象工厂模式可以创建多个。

 





原文地址:https://www.cnblogs.com/ut2016-progam/p/5307914.html