《Head First 设计模式》:抽象工厂模式
正文
一、定义
抽象工厂模式提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。
要点:
- 抽象工厂允许客户使用抽象的接口来创建一组相关的产品,而不需要知道实际产品的具体产品是什么。这样一来,客户就从具体的产品中被解耦。
- 抽象工厂的任务是定义一个负责创建一组产品的接口。这个接口内的每个方法都负责创建一个产品,同时利用实现抽象工厂的子类来提供具体的做法。
- 抽象工厂的方法经常以工厂方法的方式实现。
二、实现步骤
1、创建产品抽象类
(1)产品A抽象类
/**
* 产品A抽象类
*/
public abstract class ProductA {
String name;
public String getName() {
return name;
}
}
(2)产品B抽象类
/**
* 产品B抽象类
*/
public abstract class ProductB {
String name;
public String getName() {
return name;
}
}
2、创建具体的产品,并继承产品抽象类
(1)产品A1
/**
* 产品A1
*/
public class ConcreteProductA1 extends ProductA {
public ConcreteProductA1() {
name = "ConcreteProductA1";
}
}
(2)产品A2
/**
* 产品A2
*/
public class ConcreteProductA2 extends ProductA {
public ConcreteProductA2() {
name = "ConcreteProductA2";
}
}
(3)产品B1
/**
* 产品B1
*/
public class ConcreteProductB1 extends ProductB {
public ConcreteProductB1() {
name = "ConcreteProductB1";
}
}
(4)产品B2
/**
* 产品B2
*/
public class ConcreteProductB2 extends ProductB {
public ConcreteProductB2() {
name = "ConcreteProductB2";
}
}
3、创建工厂接口,并定义创建产品的方法
也可以使用工厂抽象类,然后在创建具体工厂时继承工厂抽象类。
/**
* 抽象工厂接口
*/
public interface AbstractFactory {
/**
* 创建产品A
*/
public ProductA createProductA();
/**
* 创建产品B
*/
public ProductB createProductB();
}
4、创建具体的工厂,并实现工厂接口
(1)工厂1
/**
* 工厂1
*/
public class ConcreteFactory1 implements AbstractFactory {
@Override
public ProductA createProductA() {
return new ConcreteProductA1();
}
@Override
public ProductB createProductB() {
return new ConcreteProductB1();
}
}
(2)工厂2
/**
* 工厂2
*/
public class ConcreteFactory2 implements AbstractFactory {
@Override
public ProductA createProductA() {
return new ConcreteProductA2();
}
@Override
public ProductB createProductB() {
return new ConcreteProductB2();
}
}
5、使用工厂创建产品
public class Test {
public static void main(String[] args) {
// 工厂1
AbstractFactory factory1 = new ConcreteFactory1();
// 工厂2
AbstractFactory factory2 = new ConcreteFactory2();
// 工厂1创建产品
ProductA productA = factory1.createProductA();
System.out.println("工厂1创建产品A:" + productA.getName());
ProductB productB = factory1.createProductB();
System.out.println("工厂1创建产品B:" + productB.getName());
// 工厂2创建产品
productA = factory2.createProductA();
System.out.println("工厂2创建产品A:" + productA.getName());
productB = factory2.createProductB();
System.out.println("工厂2创建产品B:" + productB.getName());
}
}
三、举个栗子
1、背景
假设你有一个披萨店,并且拥有许多加盟店。为了确保每家加盟店都能使用高质量的原料,你打算建造生产原料的工厂,并将原料运送到各家加盟店。
由于加盟店坐落在不同的区域,每个区域的原料是不一样的。因此,必须能够针对不同的区域提供相应的原料。
2、实现
为每个区域建造一个工厂,每个工厂负责创建相应区域的原料。
(1)创建所有原料抽象类
/**
* 面团抽象类
*/
public abstract class Dough {
String name;
public String getName() {
return name;
}
}
/**
* 酱料抽象类
*/
public abstract class Sauce {
String name;
public String getName() {
return name;
}
}
/**
* 芝士抽象类
*/
public abstract class Cheese {
String name;
public String getName() {
return name;
}
}
(2)创建不同区域的所有原料
/**
* 薄皮面团
*/
public class ThinCrustDough extends Dough {
public ThinCrustDough() {
name = "Thin Crust Dough";
}
}
/**
* 厚皮面团
*/
public class ThickCrustDough extends Dough {
public ThickCrustDough() {
name = "Thick Crust Dough";
}
}
/**
* 大蒜番茄酱
*/
public class MarinaraSauce extends Sauce {
public MarinaraSauce() {
name = "Marinara Sauce";
}
}
/**
* 番茄酱
*/
public class PlumTomatoSauce extends Sauce {
public PlumTomatoSauce() {
name = "Plum Tomato Sauce";
}
}
/**
* 帕马森雷加诺干酪
*/
public class ReggianoCheese extends Cheese{
public ReggianoCheese() {
name = "Reggiano Cheese";
}
}
/**
* 马苏里拉奶酪
*/
public class MozzarellaCheese extends Cheese{
public MozzarellaCheese() {
name = "Mozzarella Cheese";
}
}
(3)创建原料工厂接口
/**
* 披萨原料工厂接口
*/
public interface PizzaIngredientFactory {
/**
* 创建面团
*/
public Dough createDough();
/**
* 创建酱料
*/
public Sauce createSauce();
/**
* 创建芝士
*/
public Cheese createCheese();
// 创建其他原料
}
(4)创建不同区域的原料工厂
/**
* 纽约原料工厂
*/
public class NYPizzaIngredientFactory implements PizzaIngredientFactory {
@Override
public Dough createDough() {
return new ThinCrustDough();
}
@Override
public Sauce createSauce() {
return new MarinaraSauce();
}
@Override
public Cheese createCheese() {
return new ReggianoCheese();
}
}
/**
* 芝加哥原料工厂
*/
public class ChicagoPizzaIngredientFactory implements PizzaIngredientFactory {
@Override
public Dough createDough() {
return new ThickCrustDough();
}
@Override
public Sauce createSauce() {
return new PlumTomatoSauce();
}
@Override
public Cheese createCheese() {
return new MozzarellaCheese();
}
}
(5)使用不同区域的原料工厂创建原料
public class Test {
public static void main(String[] args) {
// 纽约原料工厂
PizzaIngredientFactory nyFactory = new NYPizzaIngredientFactory();
// 芝加哥原料工厂
PizzaIngredientFactory chicagoFactory = new ChicagoPizzaIngredientFactory();
// 使用纽约原料工厂创建原料
Dough dough = nyFactory.createDough();
Sauce sauce = nyFactory.createSauce();
Cheese cheese = nyFactory.createCheese();
System.out.println("New York Pizza Ingredient Factory Create:");
System.out.println(" " + dough.getName());
System.out.println(" " + sauce.getName());
System.out.println(" " + cheese.getName() + "\n");
// 使用芝加哥原料工厂创建原料
dough = chicagoFactory.createDough();
sauce = chicagoFactory.createSauce();
cheese = chicagoFactory.createCheese();
System.out.println("Chicago Pizza Ingredient Factory Create:");
System.out.println(" " + dough.getName());
System.out.println(" " + sauce.getName());
System.out.println(" " + cheese.getName());
}
}
《Head First 设计模式》:抽象工厂模式的更多相关文章
- 《Android源码设计模式》--Builder模式
No1: 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示 No2: 在Android源码中,最常用到的Builder模式就是AlertDialog.Builder No3: ...
- 《Android源码设计模式》--工厂方法模式
No1: 对于一个应用程序来说,其真正的入口是在ActivityThread类中,ActivityThread中含有我们熟悉的main方法.ActivityThread是一个final类,不能被继承. ...
- 《Android源码设计模式》--状态模式--责任链模式--解释器模式--命令模式--观察者模式--备忘录模式--迭代器模式
[状态模式] No1: Wifi设置界面是一个叫做WifiSetting的Fragment实现的 No2: 在不同的状态下对于扫描Wifi这个请求的处理是完全不一样的.在初始状态下扫描请求被直接忽略, ...
- 《Android源码设计模式》--模板方法模式
No1: 模板方法模式包括:抽象类(其中定义了一系列顺序方法).具体实现类A.具体实现类B 如果子类有实现不一样的细节,重写父类的某个方法即可 No2: AsyncTask对象调用execute方法后 ...
- 《Android源码设计模式》--策略模式
No1: 定义:策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换.策略模式让算法独立于使用它的客户而独立变化. No2: 使用场景: 1)针对同一类型问题的多种处理方式,仅 ...
- 《Android源码设计模式》--原型模式
No1: 原型模式使用场景: 1)类初始化需要消耗非常多的资源,这个资源包括数据.硬件资源等,通过原型复制避免这些消耗 2)通过new产生一个对象需要非常繁琐的数据准备货访问权限,这是可以使用原型模式 ...
- 《Android源码设计模式》学习笔记之ImageLoader
微信公众号:CodingAndroid cnblog:http://www.cnblogs.com/angel88/ CSDN:http://blog.csdn.net/xinpengfei521 需 ...
- 设计模式——抽象工厂模式及java实现
设计模式--抽象工厂模式及java实现 设计模式在大型软件工程中很重要,软件工程中采用了优秀的设计模式有利于代码维护,方便日后更改和添加功能. 设计模式有很多,而且也随着时间在不断增多,其中最著名的是 ...
- 5. 星际争霸之php设计模式--抽象工厂模式
题记==============================================================================本php设计模式专辑来源于博客(jymo ...
- 《Android源码设计模式》--抽象工厂模式
No1: 4种MediaPlayer Factory分别会生成不同的MediaPlayer基类:StagefrightPlayer.NuPlayerDriver.MidiFile和TestPlayer ...
随机推荐
- Laravel表单验证提示设置多语言
默认表单提示是英文的,我们可以安装语言包构建多语言环境. 根据版本选择命令 For Laravel 7.x : run composer require caouecs/laravel-lang:~6 ...
- SpringBoot中Service实现类添加@Service却任然无法注入的问题
最近一直在研究Spring Boot.从GitHub上下载了一个my-Blog源码,一边看,一边自己尝试去实现,结果掉在坑了,研究了近一周才爬出来,特地来这博客园记录下来,一是避免自己在放这样的错误, ...
- idea2020.1.2破解,亲测可行,激活至2089年!
一.下载最新版IDEA2020安装包 官网:https://www.jetbrains.com/idea/download/ 旧版:https://www.jetbrains.com/idea/dow ...
- CentOS 6.4 安装 rar软件(tar.gz 包)并注册成功
1.下载地址: www.rarlab.com/download.htm 2.解压tar.gz文件(cd进入文件目录) # cd /home/wjshan0808/Documents # ls rarl ...
- 基于git的博客(含站点与小程序)
1 效果 静态站点: blog.makergyt.com 备用链接: github.blog.makergyt.com 小程序: 语雀:<MakerGYT blog> 2 需求分析 2.1 ...
- TJOI2013 奖学金—大根堆实现(洛谷P3963)
奖学金 题目描述 小张学院有 \(c\) 名学生,第 \(i\) 名学生的成绩为 \(ai\) ,要获得的奖学金金额为 \(bi\) . 要从这 \(c\) 名学生中挑出 \(n\) 名学生发奖学金 ...
- mac篇---使用iTerm2快捷连接SSH
大家都知道使用iTerm2连接shh 使用命令 ssh -p22 root@129.10.10.1,然后输入密码即可. 但是每次都输入还是比较麻烦的.iTerm2为我们提供了快捷的方式.三步即可完成此 ...
- numpy基础用法学习
numpy get started 导入numpy库,并查看numpy版本 import numpy as np np.__version__ '1.14.0' 一.创建ndarray 1. 使用np ...
- JVM 专题十三:运行时数据区(八)直接内存
1. 直接内存 不是虚拟机运行时数据区的一部分,也不是<Java虚拟机规范>中定义的内存区域. 直接内存是Java堆外的.直接向系统申请的内存区间. 来源于NIO,通过存在堆中的Direc ...
- How to use the functions of apply and call
Although apply and call can implement same function. However, there is a litter different between ...