《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 fabric安装
1 安装epel wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo 2 安装pip yum i ...
- IDEA版本彩虹屁插件idea-rainbow-fart,一个在你编程时疯狂称赞你的 IDEA扩展插件
缘起 是否听说过程序员鼓励师,不久前出了一款vscode的插件rainbow-fart,可以在写代码的时候,匹配到特定关键词就疯狂的拍你马屁. vscode的下载尝试过,但是作为日常将IDEA作为主力 ...
- python中 _、__、__xx__() 区别及使用场景
1.访问权限(private.public)与继承方式(只有public继承) 在面向对象编程语言中,类的属性与方法都会设置访问控制权限,从而满足我们的设计需求.一般而言,我们通常会将对象的属性设置为 ...
- 2020年学习目标之一——emacs
这两天在虚机里面安装了centos7(gnome),决定后续自己的学习一直在这个里面进行,对于编辑器我最后选择了emacs,新手一枚,不过正好也算是今年的一项学习目标吧,加油! (完)
- 每天一个Linux命令(cd)
cd cd的详细信息 cd:不是程序,跳转当前路径(只能跳转当前路径一下的路径,若是其他路径,要写完整路径) 语法:cd [目录文件] ...
- Vue中$nextTick的理解
Vue中$nextTick的理解 Vue中$nextTick方法将回调延迟到下次DOM更新循环之后执行,也就是在下次DOM更新循环结束之后执行延迟回调,在修改数据之后立即使用这个方法,能够获取更新后的 ...
- js创建函数的方式
一般一下这三种方式 第一种(函数声明): function sum1(num1,num2){ return num1+num2;} 没啥好说的 第二种(函数表达式): var sum2 = fun ...
- day23 常用模块(中)
目录 一.json&pickle模块 1 什么是序列化 2 为什么要序列化 2.1 持久保存状态 2.2 跨平台数据交互 3 如何序列化 二.shelve模块 三.configparser模块 ...
- 初学linux常见问题
学习视频:<Linux从入门到精通> 1.Linux系统与我们常用的windows系统有什么相同与不同之处? 相同之处:都是操作系统,可以安装其他的软件 不同之处:从使用方式上来看,win ...
- 使用命名管道承载gRPC
最近GRPC很火,感觉整RPC不用GRPC都快跟不上时髦了. gRPC设计 刚好需要使用一个的RPC应用系统,自然而然就盯上了它,但是它真能够解决所有问题吗?不见得,先看看他的优点: gRPC是一种与 ...