您的位置:首页 > 编程语言 > Java开发

JAVA设计模式(2) —<创建型>抽象工厂模式(Abstract Factory)

2015-10-15 13:14 706 查看


1 定义:

抽象工厂模式(Abstract Factory)
Provide an interface for creating families of related or dependent objects without specifying their concrete classes.(为创建一组相关或相互依赖的对象提供一个接口,而且无需指定它们的具体类。)


1.1 通用类图:



主要类图-1



更体现抽象工厂实质的类图及说明
(1).AbstractFactory:声明一个创建抽象产品对象的接口。
(2).CreateFactory:实现创建具体产品对象的操作。
(3).AbstractProduct:为一类产品对象声明接口。
(4).CreateProduct:定义一个将被相应具体工厂创建的产品对象,以实现AbstractProduct接口。
(5).仅使用AbstractFactory和AbstractProduct类声明的接口。


1.2 通用代码:

抽象工厂模式是工厂方法模式的升级版本,在有多个业务品种、业务分类时,通过抽象工厂模式产生需要的对象是一种非常好的解决方式。我们来看看抽象工厂的通用源代码,首先有两个互相影响的产品线(也叫做产品族,产品种类),例如汽车的左侧门和右侧门,这两个应该是数量相等的——两个对象之间的约束,每个型号的车门都是不一样的,这是产品等级结构约束的。

类图如下:



[java] view
plaincopy

public abstract class AbstractProductA {

//每个产品共有的方法

public void shareMethod(){

}

//每个产品相同方法,不同实现

public abstract void doSomething();

}

public abstract class AbstractProductB {

//每个产品共有的方法

public void shareMethod(){

}

//每个产品相同方法,不同实现

public abstract void doSomething();

}

public class ProductA_Level_1 extendsAbstractProductA {

@Override

public void doSomething() {

System.out.println("产品A等级1的实现方法");

}

}

public class ProductA_Level_2 extendsAbstractProductA {

@Override

public void doSomething() {

System.out.println("产品A等级2的实现方法");

}

}

public class ProductB_Level_1 extendsAbstractProductB {

@Override

public void doSomething() {

System.out.println("产品B等级1的实现方法");

}

}

public class ProductB_Level_2 extendsAbstractProductB {

@Override

public void doSomething() {

System.out.println("产品B等级2的实现方法");

}

}

public abstract class AbstractCreator {

//创建A产品家族

public abstract AbstractProductA createProductA();

//创建B产品家族

public abstract AbstractProductB createProductB();

}

public class Creator_Level_1 extends
AbstractCreator {

//只生产产品等级为1的A产品

public AbstractProductA createProductA() {

return new ProductA_Level_1();

}

//只生产铲平等级为1的B产品

public AbstractProductB createProductB() {

return new ProductB_Level_1();

}

}

public class Creator_Level_2 extendsAbstractCreator {

//只生产产品等级为2的A产品

publicAbstractProductA createProductA() {

return new ProductA_Level_2();

}

//只生产铲平等级为2的B产品

public AbstractProductB createProductB() {

return new ProductB_Leve


2 优点



2.1 封装性

每个产品的实现类不是高层模块要关心的,它要关心的是:接口,抽象,它不关心对象是如何创建出来的,这是由工厂类创建的,只要知道工厂类是谁,我就能创建出一个需要的对象,省时省力。


2.2 产品族内的约束为非公开状态。

在抽象工厂模式中应该有这样一个约束:约束不同等级产品的生产比例。而这样的生产过程对调用工厂类的高层模式来说是透明的,它不需要知道这个约束,它就是要一个这样的产品,具体的产品族内的约束是在工厂内实现的。


3 缺点

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


4 应用场景

抽象工厂模式的使用场景定义非常简单:一个对象族(或是一组没有任何关系的对象)都有相同的约束,则可以使用抽象工厂模式,什么意思呢?例如一个文本编辑器和一个图片处理器,都是软件实体,但是*nix下的文本编辑器和WINDOWS下的文本编辑器虽然功能和界面都相同,但是代码实现是不同的,图片处理器也是类似情况,也就是具有了共同的约束条件:操作系统类型,于是我们可以使用抽象工厂模式,产生不同操作系统下的编辑器和图片处理器。


5 注意事项

在上述缺点论述中,提到抽象工厂模式的产品族扩展比较困难,但是要清楚是产品族扩展困难,而不是产品等级。在该模式下,产品等级是非常容易扩展的,增加一个产品等级,只要增加一个工厂类负责新增加出来的产品生产任务即可。也就是说横向<产品等级>扩展容易,纵向<产品族>扩展困难。从横向扩展上来讲,抽象工厂模式还是符合开闭原则的。


6 扩展


6.1 抽象工厂模式与工厂方法模式的区别

抽象工厂模式是工厂方法模式的升级版本,他用来创建一组相关或者相互依赖的对象。
他与工厂方法模式的区别就在于,工厂方法模式针对的是一个产品等级结构;而抽象工厂模式则是针对的多个产品等级结构。在编程中,通常一个产品结构,表现为一个接口或者抽象类,也就是说,工厂方法模式提供的所有产品都是衍生自同一个接口或抽象类,而抽象工厂模式所提供的产品则是衍生自不同的接口或抽象类。
在抽象工厂模式中,有一个产品族的概念:所谓的产品族,是指位于不同产品等级结构中功能相关联的产品组成的家族。抽象工厂模式所提供的一系列产品就组成一个产品族;而工厂方法提供的一系列产品称为一个等级结构 。

我们拿生产汽车的例子来说明他们之间的区别。



在上面的类图中,两厢车和三厢车称为两个不同的等级结构;而2.0排量车和2.4排量车则称为两个不同的产品族。再具体一点,2.0排量两厢车和2.4排量两厢车属于同一个等级结构,2.0排量三厢车和2.4排量三厢车属于另一个等级结构;而2.0排量两厢车和2.0排量三厢车属于同一个产品族,2.4排量两厢车和2.4排量三厢车属于另一个产品族。

明白了等级结构和产品族的概念,就理解工厂方法模式和抽象工厂模式的区别了,如果工厂的产品全部属于同一个等级结构,则属于工厂方法模式;如果工厂的产品来自多个等级结构,则属于抽象工厂模式。在本例中,如果一个工厂模式提供2.0排量两厢车和2.4排量两厢车,那么他属于工厂方法模式;如果一个工厂模式是提供2.4排量两厢车和2.4排量三厢车两个产品,那么这个工厂模式就是抽象工厂模式,因为他提供的产品是分属两个不同的等级结构。当然,如果一个工厂提供全部四种车型的产品,因为产品分属两个等级结构,他当然也属于抽象工厂模式了。


7 范例


7.1 华为 高低端手机

(高低等级、功能机智能机)

类图如下:



[java] view
plaincopy

package _03_AbstractFactory;

public interface Phone {

//获取手机类别

public void getKind();

//获取手机功能特性

public void getFunctions();

//获取手机等级

public void getLevel();

}

public abstract class AbstractFeaturePhone implements Phone{

public void getKind() {

System.out.println("我是功能机! ");

}

public void getFunctions() {

System.out.println("我只有有限的功能!");

}

}

public class FPhone_Level_High extends AbstractFeaturePhone{

@Override

public void getLevel() {

System.out.println("高端机");

}

}

public class FPhone_Level_Low extends AbstractFeaturePhone{

@Override

public void getLevel() {

System.out.println("低端机");

}

}

public abstract class AbstractSmartPhone implements Phone{

public void getKind() {

System.out.println("我是智能机! ");

}

public void getFunctions() {

System.out.println("我有无限多的功能!");

}

}

public class SPhone_Level_High extends AbstractSmartPhone{

@Override

public void getLevel() {

System.out.println("高端机");

}

}

public class SPhone_Level_Low extends AbstractSmartPhone{

@Override

public void getLevel() {

System.out.println("低端机");

}

}

public abstract class PhoneFactory {

public abstract Phone createFeaturePhone();

public abstract Phone createSmartPhone();

}

public class Creator_Level_High extends PhoneFactory{

public Phone createFeaturePhone(){

return new FPhone_Level_High();

}

public Phone createSmartPhone() {

return new SPhone_Level_High();

}

}

public class Creator_Level_Low extends PhoneFactory{

public Phone createFeaturePhone(){

return new FPhone_Level_Low();

}

public Phone createSmartPhone() {

return new SPhone_Level_Low();

}

}

public class Client {

public static void main(String[] args) {

//第一条产线,产高端机

PhoneFactory pfh = new Creator_Level_High();

//第二条产线,产高端机

PhoneFactory pfl = new Creator_Level_Low();

Phone sh = pfh.createSmartPhone();

sh.getLevel();

sh.getKind();

sh.getFunctions();

Phone fl = pfl.createFeaturePhone();

fl.getLevel();

fl.getKind();

fl.getFunctions();

}

}

结果:

高端机

我是智能机!

我有无限多的功能!

低端机

我是功能机!

我只有有限的功能!

7.2 选择组装电脑的配件

装机工程师要组装电脑对象,需要一系列的产品对象,比如CPU、主板等,于是创建一个抽象工厂给装机工程师使用,在这个抽象工厂里面定义抽象的创建CPU和主板的方法,这个抽象工厂就相当于一个抽象的装机方案,在这个装机方案里面,各个配件是能够相互匹配的。

每个装机的客户,会提出他们自己的具体装机方案,或者是选择已有的装机方案,相当于为抽象工厂提供了具体的子类,在这些具体的装机方案类里面,会创建具体的CPU和主板实现对象。

1、先看看CPU和主板的接口

CPU接口定义的示例代码如下:

[java] view
plaincopy





/**

* CPU的接口

* @author FX_SKY

*

*/

public interface CPUApi {

/**

* 示意方法,CPU具有运算的功能

*/

public void calculate();

}

主板接口定义的示例代码如下:

[java] view
plaincopy





/**

* 主板的接口

* @author FX_SKY

*

*/

public interface MainBoardApi {

/**

* 示意方法,主板都具有安装CPU的功能

*/

public void installCPU();

}

2、具体的CPU实现

Intel CPU实现示例代码如下:

[java] view
plaincopy





/**

* Intel 的 CPU实现

* @author FX_SKY

*

*/

public class IntelCPU implements CPUApi {

/**

* CPU的针脚数目

*/

private int pins = 0;

/**

* 构造方法,传人CPU的针脚数目

* @param pins

*/

public IntelCPU(int pins) {

this.pins = pins;

}

@Override

public void calculate() {

System.out.println("now in Intel CPU,pins="+pins);

}

}

AMD CPU实现示例代码如下:

[java] view
plaincopy





/**

* AMD 的 CPU实现

* @author FX_SKY

*

*/

public class AMDCPU implements CPUApi {

/**

* CPU的针脚数目

*/

private int pins = 0;

/**

* 构造方法,传人CPU的针脚数目

* @param pins

*/

public AMDCPU(int pins) {

this.pins = pins;

}

@Override

public void calculate() {

System.out.println("now in AMD CPU,pins="+pins);

}

}

3、具体的主板实现

技嘉主板实现的示例代码如下:

[java] view
plaincopy





/**

* 技嘉主板

* @author FX_SKY

*

*/

public class GAMainBoard implements MainBoardApi {

/**

* CPU插槽的孔数

*/

private int cpuHoles = 0;

/**

* 构造方法,传人CPU插槽的孔数

* @param cpuHoles

*/

public GAMainBoard(int cpuHoles) {

this.cpuHoles = cpuHoles;

}

@Override

public void installCPU() {

System.out.println("now in GAMainBoard,cpuHoles="+cpuHoles);

}

}

华硕主板实现的示例代码如下:

[java] view
plaincopy





/**

* 华硕主板

* @author FX_SKY

*

*/

public class ASUSMainBoard implements MainBoardApi {

/**

* CPU插槽的孔数

*/

private int cpuHoles = 0;

/**

* 构造方法,传人CPU插槽的孔数

* @param cpuHoles

*/

public ASUSMainBoard(int cpuHoles) {

this.cpuHoles = cpuHoles;

}

@Override

public void installCPU() {

System.out.println("now in ASUSMainBoard,cpuHoles="+cpuHoles);

}

}

4、抽象工厂的定义,示例代码如下:

[java] view
plaincopy





/**

* 抽象工厂的接口,声明创建抽象产品对象的操作

* @author FX_SKY

*

*/

public interface AbstractFactory {

/**

* 创建CPU的对象

* @return

*/

public CPUApi createCPUApi();

/**

* 创建主板的对象

* @return

*/

public MainBoardApi createMainBoardApi();

}

5、再看看抽象工厂的实现对象,也就是具体的装机方案对象。

方案1:的实现,示例代码如下:

[java] view
plaincopy





/**

* 装机方案1:AMD CPU + 华硕主板

* 这里创建CPU和主板对象的时候,是对应的,能匹配上的

* @author FX_SKY

*

*/

public class Schema1 implements AbstractFactory {

@Override

public CPUApi createCPUApi() {

return new AMDCPU(956);

}

@Override

public MainBoardApi createMainBoardApi() {

return new ASUSMainBoard(956);

}

}

方案2:的实现,示例代码如下:

[java] view
plaincopy





/**

* 装机方案2:Intel CPU + 技嘉主板

* 这里创建CPU和主板对象的时候,是对应的,能匹配上的

* @author FX_SKY

*

*/

public class Schema2 implements AbstractFactory {

@Override

public CPUApi createCPUApi() {

return new IntelCPU(1156);

}

@Override

public MainBoardApi createMainBoardApi() {

return new GAMainBoard(1156);

}

}

6、装机工程师类的实现,示例代码如下:

[java] view
plaincopy





/**

* 装机工程师的类

* @author FX_SKY

*

*/

public class ComputerEngineer {

/**

* 定义组装电脑需要的CPU

*/

private CPUApi cpu;

/**

* 定义组装电脑需要的主板

*/

private MainBoardApi mainBoard;

public void makeComputer(AbstractFactory schema){

//1、首先准备好装机所需要的配件

prepareHardwares(schema);

//2、组装电脑

//3、测试电脑

//4、交付客户

}

private void prepareHardwares(AbstractFactory schema) {

//使用抽象工厂来获取相应的接口对象

this.cpu = schema.createCPUApi();

this.mainBoard = schema.createMainBoardApi();

//测试一下配件是否好用

this.cpu.calculate();

this.mainBoard.installCPU();

}

}

6、客户端使用抽象工厂,示例代码如下:

[java] view
plaincopy





public class Client {

/**

* @param args

*/

public static void main(String[] args) {

//创建装机工程师对象

ComputerEngineer cm = new ComputerEngineer();

//客户选择并创建需要使用的装机方案对象

Schema1 schema1 = new Schema1();

//告诉装机工程师自己的装机方案,让装机工程师组装电脑

cm.makeComputer(schema1);

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: