《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 ...
随机推荐
- python利用列表文件遍历
关键词:文件遍历/列表 思路:先制作目标文件列表(txt/csv...均可),再逐行读取列表文件 1. 制作列表 linux 终端输入:# find ./abc -type f > list.t ...
- 如何解决TOP-K问题
前言:最近在开发一个功能:动态展示的订单数量排名前10的城市,这是一个典型的Top-k问题,其中k=10,也就是说找到一个集合中的前10名.实际生活中Top-K的问题非常广泛,比如:微博热搜的前100 ...
- 浅谈auth模块
目录 auth模块 什么是Auth模块 auth模块的常用方法 用户注册 扩展默认的auth_user表 auth模块 什么是Auth模块 auth模块是对注册登录认证注销修改密码等方法的一种封装 ...
- P4817 Fruit Feast G
最开始拿到这道题的时候,题目中其实只规定了两种水果的饱食度,可以理解成价值或是重量,在不超过T的情况求最大值.第一眼看过去感觉就是装箱问题(背包),只不过这道题用的是完全背包,但是考虑到喝水的情况,做 ...
- NPOI 操作数据库中数据的导入导出(Excel.xls文件) 和null数据的处理。
App.config: <?xml version="1.0" encoding="utf-8" ?> <configuration> ...
- Drozer简单使用
1.Drozer简介 Drozer是一款针对Android系统的安全测试框架.Drozer可以通过与dalivik VM交互.与其他应用程序的IPC端点交互.与底层操作系统的交互,来避免正处于开发 ...
- CF1215D Ticket Game(思维,博弈)
题目 传送门:https://www.luogu.com.cn/problem/CF1215D Idea 一列数,保证能分成左右两部分,其中有若干个数字被抹掉,两个人轮流填数,如果在把这些空缺的数字填 ...
- Mysql中交换行操作
博客已搬家,更多内容查看https://liangyongrui.github.io/ Mysql中交换行操作 leetcode的一道题目 参考:https://leetcode.com/proble ...
- BZOJ1294 洛谷P2566 状态压缩DP 围豆豆
传送门 题目描述 是不是平时在手机里玩吃豆豆游戏玩腻了呢?最近MOKIA手机上推出了一种新的围豆豆游戏,大家一起来试一试吧游戏的规则非常简单,在一个N×M的矩阵方格内分布着D颗豆子,每颗豆有不同的分值 ...
- Django---进阶1
目录 静态文件配置 request对象方法初识 pycharm链接数据库(MySQL) django链接数据库(MySQL) Django ORM 字段的增删改查 数据的增删改查 今日作业 静态文件配 ...