1.场景模拟

举个生活中常见的例子:组装电脑,我们在组装电脑的时候,通常要选择一系列的配件,比如选择CPU时候,需要注意品牌,型号,针脚数目,主频,只有这些都确定下来,才能确定一个CPU。同样,主板也是这样的。对于装机工程师而言,他只知道装一台电脑需要使用相应的配件,具体的配件,还是由客户说了算。

2.一般的解决方案(简单工厂)

2.1CPU接口

package demo06.abstractfactory.example1;

/**
* CPU的接口
*/
public interface CPUApi {
/**
* 示意方法,CPU具有运算的功能
*/
public void calculate();
}

2.2主板接口

package demo06.abstractfactory.example1;

/**
* 主板的接口
*/
public interface MainboardApi {
/**
* 示意方法,主板都具有安装CPU的功能
*/
public void installCPU();
}

2.3 Inter CPU实现

package demo06.abstractfactory.example1;

/**
* Intel的CPU实现
*/
public class IntelCPU implements CPUApi {
/**
* CPU的针脚数目
*/
private int pins = 0; /**
* 构造方法,传入CPU的针脚数目
*
* @param pins
* CPU的针脚数目
*/
public IntelCPU(int pins) {
this.pins = pins;
} public void calculate() {
System.out.println("now in Intel CPU,pins=" + pins);
}
}

2.4 AMD的CPU实现

package demo06.abstractfactory.example1;

/**
* AMD的CPU实现
*/
public class AMDCPU implements CPUApi {
/**
* CPU的针脚数目
*/
private int pins = 0; /**
* 构造方法,传入CPU的针脚数目
*
* @param pins
* CPU的针脚数目
*/
public AMDCPU(int pins) {
this.pins = pins;
} public void calculate() {
System.out.println("now in AMD CPU,pins=" + pins);
}
}

2.5技嘉的主板实现

package demo06.abstractfactory.example1;

/**
* 技嘉的主板
*/
public class GAMainboard implements MainboardApi {
/**
* CPU插槽的孔数
*/
private int cpuHoles = 0; /**
* 构造方法,传入CPU插槽的孔数
*
* @param cpuHoles
* CPU插槽的孔数
*/
public GAMainboard(int cpuHoles) {
this.cpuHoles = cpuHoles;
} public void installCPU() {
System.out.println("now in GAMainboard,cpuHoles=" + cpuHoles);
}
}

2.6微星的主板

package demo06.abstractfactory.example1;

/**
* 微星的主板
*/
public class MSIMainboard implements MainboardApi {
/**
* CPU插槽的孔数
*/
private int cpuHoles = 0; /**
* 构造方法,传入CPU插槽的孔数
*
* @param cpuHoles
* CPU插槽的孔数
*/
public MSIMainboard(int cpuHoles) {
this.cpuHoles = cpuHoles;
} public void installCPU() {
System.out.println("now in MSIMainboard,cpuHoles=" + cpuHoles);
}
}

2.7创建CPU工厂

package demo06.abstractfactory.example1;
/**
* 创建CPU的简单工厂
*/
public class CPUFactory {
/**
* 创建CPU接口对象的方法
* @param type 选择CPU类型的参数
* @return CPU接口对象的方法
*/
public static CPUApi createCPUApi(int type){
CPUApi cpu = null;
//根据参数来选择并创建相应的CPU对象
if(type==1){
cpu = new IntelCPU(1156);
}else if(type==2){
cpu = new AMDCPU(939);
}
return cpu;
}
}

2.8创建主板工厂

package demo06.abstractfactory.example1;

/**
* 创建主板的简单工厂
*/
public class MainboardFactory {
/**
* 创建主板接口对象的方法
*
* @param type
* 选择主板类型的参数
* @return 主板接口对象的方法
*/
public static MainboardApi createMainboardApi(int type) {
MainboardApi mainboard = null;
// 根据参数来选择并创建相应的主板对象
if (type == 1) {
mainboard = new GAMainboard(1156);
} else if (type == 2) {
mainboard = new MSIMainboard(939);
}
return mainboard;
}
}

2.9工程师实现代码

package demo06.abstractfactory.example1;

/**
* 装机工程师的类
*/
public class ComputerEngineer {
/**
* 定义组装机器需要的CPU
*/
private CPUApi cpu = null;
/**
* 定义组装机器需要的主板
*/
private MainboardApi mainboard = null; /**
* 装机过程
*
* @param cpuType
* 客户选择所需CPU的类型
* @param mainboardType
* 客户选择所需主板的类型
*/
public void makeComputer(int cpuType, int mainboardType) {
// 1:首先准备好装机所需要的配件
prepareHardwares(cpuType, mainboardType);
// 2:组装机器 // 3:测试机器 // 4:交付客户
} /**
* 准备装机所需要的配件
*
* @param cpuType
* 客户选择所需CPU的类型
* @param mainboardType
* 客户选择所需主板的类型
*/
private void prepareHardwares(int cpuType, int mainboardType) {
// 这里要去准备CPU和主板的具体实现,为了示例简单,这里只准备这两个
// 可是,装机工程师并不知道如何去创建,怎么办呢? // 直接找相应的工厂获取
this.cpu = CPUFactory.createCPUApi(cpuType);
this.mainboard = MainboardFactory.createMainboardApi(mainboardType); // 测试一下配件是否好用
this.cpu.calculate();
this.mainboard.installCPU();
}
}

2.90客户端测试

package demo06.abstractfactory.example1;

public class Client {
public static void main(String[] args) {
// 创建装机工程师对象
ComputerEngineer engineer = new ComputerEngineer();
// 告诉装机工程师自己选择的配件,让装机工程师组装电脑
engineer.makeComputer(1, 2);
}
}

3.问题:

问题出现了:如果client传入的参数时1,2,那么装机不匹配就会失败,所以就会出现问题,如何解决呢?

4.解决方法(抽象工厂模式)

4.1模式定义:

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

4.2模式的结构和说明

5.示例代码(抽象工厂模式)

5.1抽象工厂接口

package demo06.abstractfactory.example2;

/**
* 抽象工厂的接口,声明创建抽象产品对象的操作
*/
public interface AbstractFactory {
/**
* 示例方法,创建抽象产品A的对象
*
* @return 抽象产品A的对象
*/
public AbstractProductA createProductA(); /**
* 示例方法,创建抽象产品B的对象
*
* @return 抽象产品B的对象
*/
public AbstractProductB createProductB();
}

5.2产品A接口

package demo06.abstractfactory.example2;

/**
* 抽象产品A的接口
*/
public interface AbstractProductA {
// 定义抽象产品A相关的操作
}

5.3产品B接口

package demo06.abstractfactory.example2;

/**
* 抽象产品B的接口
*/
public interface AbstractProductB {
// 定义抽象产品B相关的操作
}

5.4产品A实现

package demo06.abstractfactory.example2;

/**
* 产品A的具体实现
*/
public class ProductA1 implements AbstractProductA {
// 实现产品A的接口中定义的操作
} package demo06.abstractfactory.example2; /**
* 产品A的具体实现
*/
public class ProductA2 implements AbstractProductA {
// 实现产品A的接口中定义的操作
}

5.5产品B实现

package demo06.abstractfactory.example2;

/**
* 产品B的具体实现
*/
public class ProductB1 implements AbstractProductB {
// 实现产品B的接口中定义的操作
} package demo06.abstractfactory.example2; /**
* 产品B的具体实现
*/
public class ProductB2 implements AbstractProductB {
// 实现产品B的接口中定义的操作
}

5.6具体工厂实现

package demo06.abstractfactory.example2;

/**
* 具体的工厂实现对象,实现创建具体的产品对象的操作
*/
public class ConcreteFactory1 implements AbstractFactory { public AbstractProductA createProductA() {
return new ProductA1();
}
public AbstractProductB createProductB() {
return new ProductB1();
}
} package demo06.abstractfactory.example2; /**
* 具体的工厂实现对象,实现创建具体的产品对象的操作
*/
public class ConcreteFactory2 implements AbstractFactory { public AbstractProductA createProductA() {
return new ProductA2();
}
public AbstractProductB createProductB() {
return new ProductB2();
}
}

5.7客户端

package demo06.abstractfactory.example2;

public class Client {

	public static void main(String[] args) {
// 创建抽象工厂对象
AbstractFactory af = new ConcreteFactory1();
// 通过抽象工厂来获取一系列的对象,如产品A和产品B
af.createProductA();
af.createProductB();
}
}

6.重写示例代码

6.1结构图

6.2抽象工厂接口

package demo06.abstractfactory.example3;

/**
* 抽象工厂的接口,声明创建抽象产品对象的操作
*/
public interface AbstractFactory {
/**
* 创建CPU的对象
*
* @return CPU的对象
*/
public CPUApi createCPUApi(); /**
* 创建主板的对象
*
* @return 主板的对象
*/
public MainboardApi createMainboardApi();
}

6.3装机方案一

package demo06.abstractfactory.example3;

/**
* 装机方案一:Intel 的CPU + 技嘉的主板 这里创建CPU和主板对象的时候,是对应的,能匹配上的
*/
public class Schema1 implements AbstractFactory {
public CPUApi createCPUApi() {
return new IntelCPU(1156);
} public MainboardApi createMainboardApi() {
return new GAMainboard(1156);
}
}

6.4装机方案二

package demo06.abstractfactory.example3;

/**
* 装机方案二:AMD的CPU + 微星的主板 这里创建CPU和主板对象的时候,是对应的,能匹配上的
*/
public class Schema2 implements AbstractFactory {
public CPUApi createCPUApi() {
return new AMDCPU(939);
} public MainboardApi createMainboardApi() {
return new MSIMainboard(939);
}
}

6.5装机工程师

package demo06.abstractfactory.example3;

/**
* 装机工程师的类
*/
public class ComputerEngineer {
/**
* 定义组装机器需要的CPU
*/
private CPUApi cpu = null;
/**
* 定义组装机器需要的主板
*/
private MainboardApi mainboard = null; /**
* 装机过程
*
* @param schema
* 客户选择的装机方案
*/
public void makeComputer(AbstractFactory schema) {
// 1:首先准备好装机所需要的配件
prepareHardwares(schema);
// 2:组装机器 // 3:测试机器 // 4:交付客户
} /**
* 准备装机所需要的配件
*
* @param schema
* 客户选择的装机方案
*/
private void prepareHardwares(AbstractFactory schema) {
// 这里要去准备CPU和主板的具体实现,为了示例简单,这里只准备这两个
// 可是,装机工程师并不知道如何去创建,怎么办呢? // 使用抽象工厂来获取相应的接口对象
this.cpu = schema.createCPUApi();
this.mainboard = schema.createMainboardApi(); // 测试一下配件是否好用
this.cpu.calculate();
this.mainboard.installCPU();
}
}

6.6客户端使用

package demo06.abstractfactory.example3;

public class Client {
public static void main(String[] args) {
// 创建装机工程师对象
ComputerEngineer engineer = new ComputerEngineer();
// 客户选择并创建需要使用的装机方案对象
AbstractFactory schema = new Schema1();
// 告诉装机工程师自己选择的装机方案,让装机工程师组装电脑
engineer.makeComputer(schema);
}
}

7.抽象工厂模式讲解

7.1抽象工厂和DAO

DAO是数据访问对象,是J2EE中的一种标准的模式,是为了解决访问数据不同而产生的一种设计模式。这种设计模式简言之是:分层设计的思想。
在实现DAO模式的时候,多用工厂的策略,最常用的就是抽象工厂模式,当然最好结合工厂方法模式。

7.2抽象工厂的优缺点

优点:分离接口和实现

使得切换产品簇更加容易。

缺点:不太容易扩展新的产品

容易造成类层次复杂

7.3抽象工厂模式的本质

选择产品簇的实现

设计模式08---设计模式之抽象工厂模式(Abstract Factory)的更多相关文章

  1. .NET设计模式(2):1.2 抽象工厂模式(Abstract Factory)

    概述 抽象工厂模式(Abstract Factory)是所有形态的工厂模式中最为抽象和最具一般性的一种形态.抽象工厂模式是指当有多个抽象角色时,使用的一种工厂模式.抽象工厂模式可以向客户端提供一个接口 ...

  2. 设计模式之十一:抽象工厂模式(Abstract Factory)

    抽象工厂模式: 提供了一个创建一系列相关的或相互依赖的对象的接口而不须要详细指定它们的类型. Provide an interface for creating families of related ...

  3. 乐在其中设计模式(C#) - 抽象工厂模式(Abstract Factory Pattern)

    原文:乐在其中设计模式(C#) - 抽象工厂模式(Abstract Factory Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 抽象工厂模式(Abstract Factor ...

  4. 【设计模式】抽象工厂模式 Abstract Factory Pattern

    简单工厂模式是一个工厂类根据工厂方法的参数创建不出不同的产品, 工厂方法模式是每一个产品都有一个一一对应的工厂负责创建该产品.那么今天要讲的抽象工厂模式是一个工厂能够产生关联的一系列产品.抽象工厂模式 ...

  5. 设计模式 - 抽象工厂模式(abstract factory pattern) 具体解释

    抽象工厂模式(abstract factory pattern) 详细解释 本文地址: http://blog.csdn.net/caroline_wendy/article/details/2709 ...

  6. 二十四种设计模式:抽象工厂模式(Abstract Factory Pattern)

    抽象工厂模式(Abstract Factory Pattern) 介绍提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类. 示例有Message和MessageModel,Messag ...

  7. 【UE4 设计模式】抽象工厂模式 Abstract Factory Pattern

    概述 描述 提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类:具体的工厂负责实现具体的产品实例 抽象工厂中每个工厂可以创建多种产品(如苹果公司生产iPhone.iPad): 工厂方法 ...

  8. 抽象工厂模式(Abstract Factory)C#实例

    抽象工厂模式(Abstract Factory)C#实例 本文出处http://www.dofactory.com/net/abstract-factory-design-pattern 一.场景描述 ...

  9. 设计模式的征途—3.抽象工厂(Abstract Factory)模式

    上一篇的工厂方法模式引入了工厂等级结构,解决了在原来简单工厂模式中工厂类职责太重的原则,但是由于工厂方法模式的每个工厂只生产一类产品,可能会导致系统中存在大量的工厂类,从而增加系统开销.那么,我们应该 ...

  10. 设计模式的征途—4.抽象工厂(Abstract Factory)模式

    上一篇的工厂方法模式引入了工厂等级结构,解决了在原来简单工厂模式中工厂类职责太重的原则,但是由于工厂方法模式的每个工厂只生产一类产品,可能会导致系统中存在大量的工厂类,从而增加系统开销.那么,我们应该 ...

随机推荐

  1. 关于Android开发中导出jar包后的资源使用问题解决

    我们经常遇到一个需求,就是给别人使用我们工程的时候,为了能够屏蔽代码,把代码封装成jar包提供给第三方使用,但是这样我们的资源文件怎么给对方用呢? 其实并不用这么的复杂,下面就介绍一下具体的方法 一, ...

  2. (C语言)共用体union的使用方法举例

    曾经在学校学习C语言的时候一直搞不懂那个共用体union有什么用的.工作之后才发现它的一些妙用,现举比例如以下: 1. 为了方便看懂代码. 比方说想写一个3 * 3的矩阵,能够这样写: [ 注:以下用 ...

  3. Backbone入门

    Backbone入门讲解 Backbone是一个实现了web前端mvc模式的js框架. 一种解决问题的通用方法,我们叫做模式. 设计模式:工厂模式,适配器模式,观察者模式等,推荐js设计模式这本书.设 ...

  4. DELL iDRAC 远程虚拟机报错:虚拟介质分离或所选虚拟磁盘驱动器的虚拟介质重定向已由另一用户使用

    原因很简单,那就是虚拟介质的映射功能,只能被使用一次. 推荐做法: 1.由于通过远程,在Lifecycle Controller里DeployOS安装系统,需要在虚拟介质里映射ISO,因此映射功能要留 ...

  5. Python 2.7.3 urllib2.urlopen 获取网页出现乱码解决方案

    出现乱码的原因是,网页服务端有bug,它硬性使用使用某种特定的编码方案,而并没有按照客户端的请求头的编码要求来发送编码. 解决方案:使用chardet来猜测网页编码. 1.去chardet官网下载ch ...

  6. C# & WPF 随手小记之一 ——初探async await 实现多线程处理

    嗯...我也是在园子待了不短时间的人了,一直以来汲取着园友的知识,感觉需要回馈什么. 于是以后有空我都会把一些小技巧小知识写下来,有时候可能会很短甚至很简单,但希望能帮到大家咯. 第一篇文章来说说as ...

  7. Mac OSX系统安装和配置Zend Server 6教程(2)

    继上一节安装好Zend Server 6以后,我们需要修改配置文件.首先修改服务器监听端口.默认的情况下Zend Server 6安装以后的端口是10088.一般开发者使用的都是HTTP默认端口80. ...

  8. 使用Windows2003创建DNS服务器 - 进阶者系列 - 学习者系列文章

    Windows 2003的DNS服务器的配置还是比较简单的.下面简要介绍下DNS服务器的配置. 1.    打开控制面板,选择 添加删除Windows组件,选择 网络服务 ,选择 详细信息,选择 域名 ...

  9. javascript脚本化文档

    1.getElememtById /** * 获取指定id的的元素数组 */ function getElements(/*ids...*/) { var elements = {}; for(var ...

  10. .NET和JAVA的比较- 体系结构

    .NET体系结构   对于.NET Framework体系结构,参考了"你必须知道的.NET"并”借用“别人的经典体系结构图从宏观上说明一下我的理解. 图1 简单的说下几个名词: ...