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 通用类图:
![](http://my.csdn.net/uploads/201205/14/1336982977_4555.png)
主要类图-1
![](https://oscdn.geek-share.com/Uploads/Images/Content/201510/4dc81c375c98ee2182f8da2461b32015.gif)
更体现抽象工厂实质的类图及说明
(1).AbstractFactory:声明一个创建抽象产品对象的接口。
(2).CreateFactory:实现创建具体产品对象的操作。
(3).AbstractProduct:为一类产品对象声明接口。
(4).CreateProduct:定义一个将被相应具体工厂创建的产品对象,以实现AbstractProduct接口。
(5).仅使用AbstractFactory和AbstractProduct类声明的接口。
1.2 通用代码:
抽象工厂模式是工厂方法模式的升级版本,在有多个业务品种、业务分类时,通过抽象工厂模式产生需要的对象是一种非常好的解决方式。我们来看看抽象工厂的通用源代码,首先有两个互相影响的产品线(也叫做产品族,产品种类),例如汽车的左侧门和右侧门,这两个应该是数量相等的——两个对象之间的约束,每个型号的车门都是不一样的,这是产品等级结构约束的。类图如下:
![](http://my.csdn.net/uploads/201205/14/1336995120_2348.png)
[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 抽象工厂模式与工厂方法模式的区别
抽象工厂模式是工厂方法模式的升级版本,他用来创建一组相关或者相互依赖的对象。他与工厂方法模式的区别就在于,工厂方法模式针对的是一个产品等级结构;而抽象工厂模式则是针对的多个产品等级结构。在编程中,通常一个产品结构,表现为一个接口或者抽象类,也就是说,工厂方法模式提供的所有产品都是衍生自同一个接口或抽象类,而抽象工厂模式所提供的产品则是衍生自不同的接口或抽象类。
在抽象工厂模式中,有一个产品族的概念:所谓的产品族,是指位于不同产品等级结构中功能相关联的产品组成的家族。抽象工厂模式所提供的一系列产品就组成一个产品族;而工厂方法提供的一系列产品称为一个等级结构 。
我们拿生产汽车的例子来说明他们之间的区别。
![](https://oscdn.geek-share.com/Uploads/Images/Content/201510/8a55999e6e0b2728658ac4dd06862a61.gif)
在上面的类图中,两厢车和三厢车称为两个不同的等级结构;而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 华为 高低端手机
(高低等级、功能机智能机)类图如下:
![](http://my.csdn.net/uploads/201205/14/1336995164_5991.png)
[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
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
/**
* CPU的接口
* @author FX_SKY
*
*/
public interface CPUApi {
/**
* 示意方法,CPU具有运算的功能
*/
public void calculate();
}
主板接口定义的示例代码如下:
[java] view
plaincopy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
/**
* 主板的接口
* @author FX_SKY
*
*/
public interface MainBoardApi {
/**
* 示意方法,主板都具有安装CPU的功能
*/
public void installCPU();
}
2、具体的CPU实现
Intel CPU实现示例代码如下:
[java] view
plaincopy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
/**
* 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
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
/**
* 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
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
/**
* 技嘉主板
* @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
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
/**
* 华硕主板
* @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
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
/**
* 抽象工厂的接口,声明创建抽象产品对象的操作
* @author FX_SKY
*
*/
public interface AbstractFactory {
/**
* 创建CPU的对象
* @return
*/
public CPUApi createCPUApi();
/**
* 创建主板的对象
* @return
*/
public MainBoardApi createMainBoardApi();
}
5、再看看抽象工厂的实现对象,也就是具体的装机方案对象。
方案1:的实现,示例代码如下:
[java] view
plaincopy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
/**
* 装机方案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
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
/**
* 装机方案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
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
/**
* 装机工程师的类
* @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
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
public class Client {
/**
* @param args
*/
public static void main(String[] args) {
//创建装机工程师对象
ComputerEngineer cm = new ComputerEngineer();
//客户选择并创建需要使用的装机方案对象
Schema1 schema1 = new Schema1();
//告诉装机工程师自己的装机方案,让装机工程师组装电脑
cm.makeComputer(schema1);
}
}
相关文章推荐
- Myeclipse中如何修改svn用户名密码
- spring 多数据源注解事务使用
- Java基础教程
- springMVC传对象参数、返回JSON格式数据
- struts2 helloworld
- 做开发几年的个人经历
- Struts2漏洞修复到2.3.15.1版本步骤
- Java字节流和字符流学习和笔记——黑马训练营
- Java并发编程:Timer和TimerTask
- spring mvc 将页面string类型日期转换为后台Date日期
- Java中ModelAndView是做什么的?
- mac下 netbeans 8.02中文版设置代码自动补齐 + eclipse自动补齐
- spring aop的实现方式(二)
- java collection 类图
- spring @Configuration 和 @Bean
- 从头认识java-1.3 隐藏具体实现
- eclipse 条件断点
- 从头认识java-1.3 隐藏具体实现
- Java核心技术第6章(3)
- Java之旅(三)--- JSTL和EL表情