《JAVA设计模式》之抽象工厂模式

来源:互联网 发布:鼠标手写输入软件 编辑:程序博客网 时间:2024/06/06 03:19

一.举例

抽象工厂和简单工厂相比,有很多相似的地方。这里我就先举个例子直接介绍了。
网上有很多博客都以这个例子举例的,下面我也以这个例子进入介绍了

想组装一台电脑,需要买很多东西,比如CPU,GPU,声卡,主板,电源,风扇等,这里为了方便我们就只考虑CPU和主板了。
CPU又分为两个品牌的CPU,Inter和AMD的,而主板也分为这两个品牌,而两个品牌的不能相互使用,就是说不能用Inter的CPU和AMD的主板组装,AMD的针脚数和CPU上的插口数不一致,相同的AMD的CPU也不能与Inter的主板组装的。

对于装机工程师而言,他只知道组装一台电脑,需要相应的配件,但是具体使用什么样的配件,还得由客户说了算。也就是说装机工程师只是负责组装,而客户负责选择装配所需要的具体的配件。因此,当装机工程师为不同的客户组装电脑时,只需要根据客户的装机方案,去获取相应的配件,然后组装即可。

我们可以试试用简单工厂来进行实现,下面的UML就是大致结构
这里写图片描述

这是简单工厂模式的结构
这里写图片描述

简单工厂模式代码如下:

public interface Board {      //主板的插口数      public void boardCount();}
public interface Cpu {        //CPU针脚数         public void cal();}
public class AmdBoard implements Board{    /*     * Amd主板插口数     */    private int AmdBoardCount;    public AmdBoard(int AmdBoardCount) {              this.AmdBoardCount=AmdBoardCount;    }    @Override    public void boardCount() {        System.out.println("AmdBoard插口数"+AmdBoardCount);    }}
public class AmdCpu implements Cpu{    /*     * AmdCpu的针脚数     */    private int AmdCpuCount;    public AmdCpu(int AmdCpuCount) {           this.AmdCpuCount=AmdCpuCount;    }    @Override    public void cal() {        System.out.println("AmdCpu的针脚数"+AmdCpuCount);    }}
public class IntelBoard implements Board{    /*     * Intel主板插口数     */    private int IntelBoardCount;    public IntelBoard(int IntelBoardCount) {        this.IntelBoardCount=IntelBoardCount;    }    @Override    public void boardCount() {        System.out.println("IntelBoard插口数"+IntelBoardCount);    }}
public class IntelCpu implements Cpu{    /*     * IntelCpu针脚数     */    private int IntelCpuCount;    public IntelCpu(int IntelCpuCount) {          this.IntelCpuCount=IntelCpuCount;    }    @Override    public void cal() {        System.out.println("IntelCpu的针脚数"+IntelCpuCount);    }}
public class Computer {      private Cpu cpu=null;      private Board board=null;      public void getComputer(String Cputype,String Boardtype) throws InstantiationException, IllegalAccessException {                 createComputer(Cputype,Boardtype);      }    public void createComputer(String cputype, String boardtype) throws InstantiationException, IllegalAccessException {            cpu=CpuFactory.getCpu(cputype);                 board=BoardFactory.getBoard(boardtype);            cpu.cal();                      board.boardCount();    }}
public class testDemo {         public static void main(String[] args) throws InstantiationException, IllegalAccessException {              Computer computer=new Computer();              computer.createComputer("Intel","Intel");              System.out.println("**************");              computer.createComputer("Intel","Amd");                  }}

运行结果:
这里写图片描述

但我们发现如果选择Intel的CPU和Amd的主板,将会无法进行组装,这个怎么办呢???下面我们就来介绍介绍抽象工厂的基础概念吧

二.引进抽象工厂

每一个模式都是针对一定问题的解决方案。抽象工厂模式与工厂方法模式的最大区别就在于,工厂方法模式针对的是一个产品等级结构;而抽象工厂模式则需要面对多个产品等级结构。
在学习抽象工厂具体实例之前,应该明白两个重要的概念:产品族和产品等级。
所谓产品族,是指位于不同产品等级结构中,功能相关联的产品组成的家族。比如AMD的主板、芯片组、CPU组成一个家族,Intel的主板、芯片组、CPU组成一个家族。而这两个家族都来自于三个产品等级:主板、芯片组、CPU。一个等级结构是由相同的结构的产品组成,示意图如下:

这里写图片描述

显然,每一个产品族中含有产品的数目,与产品等级结构的数目是相等的。产品的等级结构与产品族将产品按照不同方向划分,形成一个二维的坐标系。横轴表示产品的等级结构,纵轴表示产品族,上图共有两个产品族,分布于三个不同的产品等级结构中。只要指明一个产品所处的产品族以及它所属的等级结构,就可以唯一的确定这个产品。
  上面所给出的三个不同的等级结构具有平行的结构。因此,如果采用工厂方法模式,就势必要使用三个独立的工厂等级结构来对付这三个产品等级结构。由于这三个产品等级结构的相似性,会导致三个平行的工厂等级结构。随着产品等级结构的数目的增加,工厂方法模式所给出的工厂等级结构的数目也会随之增加。如下图:
这里写图片描述

但是如果我们采用如下的操作,那么问题就会随之解决

这里写图片描述
  

可以看出,一个工厂等级结构可以创建出分属于不同产品等级结构的一个产品族中的所有对象。显然,这时候抽象工厂模式比简单工厂模式、工厂方法模式更有效率。对应于每一个产品族都有一个具体工厂。而每一个具体工厂负责创建属于同一个产品族,但是分属于不同等级结构的产品。

三.抽象工厂模式结构

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

四.抽象工厂模式实现

其中assembly和Impl包下的不变

public interface AbstractFactory {      public Cpu createCput();      public Board createBoard();}
public class AmdFactory implements AbstractFactory{    //创建Amd品牌的CPU    @Override    public Cpu createCput() {        return new AmdCpu(250);    }    //创建Amd品牌的主板    @Override    public Board createBoard() {        return new AmdBoard(250);    }}
public class InterFactory implements AbstractFactory{    //创建Inter品牌的Cpu    @Override    public Cpu createCput() {        return new IntelCpu(3600);    }    //创建Inter品牌的主板    @Override    public Board createBoard() {        return new IntelBoard(3600);    }}
public class Computer {      private Cpu cpu=null;      private Board board=null;      public void getComputer(AbstractFactory af) {             createComputer(af);      }      public void createComputer(AbstractFactory af) {                  cpu=af.createCput();                  board=af.createBoard();                  cpu.cal();                  board.boardCount();      }}
public  class testDemo {         public static void main(String[] args) throws InstantiationException, IllegalAccessException {                Computer computer=new Computer();                AbstractFactory af1=new AmdFactory();                computer.createComputer(af1);                System.out.println("**********************");                AbstractFactory af2=new InterFactory();                computer.createComputer(af2);        }}

运行结果:
这里写图片描述

总结:
在什么情况下应该使用抽象工厂模式?

  • 一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节,这对于所有形态的工厂模式都是重要的。
  • 这个系统的产品有多于一个的产品族,而系统只消费其中某一族的产品。
  • 同属于同一个产品族的产品是在一起使用的,这一约束必须在系统的设计中体现出来。(比如:Intel主板必须使用Intel CPU、Intel芯片组)
  • 系统提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于实现。

抽象工厂模式的优点

  • 分离接口和实现
    • 客户端使用抽象工厂来创建需要的对象,而客户端根本就不知道具体的实现是谁,客户端只是面向产品的接口编程而已。也就是说,客户端从具体的产品实现中解耦。
  • 使切换产品族变得容易
    • 因为一个具体的工厂实现代表的是一个产品族,比如上面例子的从Intel系列到AMD系列只需要切换一下具体工厂。

抽象工厂模式的缺点

  • 不太容易扩展新的产品
    • 如果需要给整个产品族添加一个新的产品,那么就需要修改抽象工厂,这样就会导致修改所有的工厂实现类。
2 0
原创粉丝点击