我们打算做一个制作pizza的系统,从订购到出货,初始代码如下:
public class Pizza{ Pizza orderPizza(String type){ Pizza pizza; // 会引起代码变化的部分 if(type.equals("cheese")){ pizza =new CheesePizza(); }else if (type.equals("greek")){ pizza=new GreekPizza(); }else if(type.equals("pepperoni")){ pizza=new pepperoniPizza(); } //不需要改变的部分代码 这是对pizza的一系列处理 pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); return pizza; }}
public class Pizza{
Pizza orderPizza(String type){
Pizza pizza;
// 会引起代码变化的部分
if(type.equals("cheese")){
pizza =new CheesePizza();
}else if (type.equals("greek")){
pizza=new GreekPizza();
}else if(type.equals("pepperoni")){
pizza=new pepperoniPizza();
}
//不需要改变的部分代码 这是对pizza的一系列处理
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
客户端通过调用pizza类的orderPizza方法来创建pizza,根据type的不同来获取不同种类的pizza,然而以上的设计存在着很多问题:
因此我们引出了简单工厂模式,此模式能在一定程度上解决这个问题。
简单工厂模式
此模式能在一定程度上解决这个问题
简单工厂模式不属于GoF23个经典设计模式,但它是学习工厂模式的基础,其思想:首先将需要创建的各种对象(各种风味pizza)封装到不同对象中,这些类称为具体产品类,将公共部分提取到抽象产品类,然后提供一个工厂类用于创建各种产品,在工厂类中提供创建产品的工厂方法,根据参数获取不同的产品对象。
具体产品类
抽象产品类
工厂类
其定义如下:
简单工厂模式(Simple Factory Pattern):定义一个工厂类,它可以根据参数的不同返回不同类的实例,被创建的实例通常都具有共同的父类。因为在简单工厂模式中用于创建实例的方法是静态(static)方法,因此简单工厂模式又被称为静态工厂方法(Static Factory Method)模式,它属于类创建型模式。
Factory(工厂角色)
Product(抽象产品角色)
ProductA(具体产品角色)
在简单工厂模式中
抽象产品角色:
public interface IPizza { void prepare(); void bake(); void cut(); void box();}
public interface IPizza {
void prepare();
void bake();
void cut();
void box();
具体产品A:
public class PizzaA implements IPizza { @Override public void prepare() { } @Override public void bake() { } @Override public void cut() { } @Override public void box() { }}
public class PizzaA implements IPizza {
@Override
public void prepare() {
public void bake() {
public void cut() {
public void box() {
具体产品B:
public class PizzaB implements IPizza { @Override public void prepare() { } @Override public void bake() { } @Override public void cut() { } @Override public void box() { }}
public class PizzaB implements IPizza {
工厂角色:
public class SimplePizzaFactory { public static IPizza createPizza(String type){ IPizza pizza=null; if(type.equals("A")){ pizza =new PizzaA(); }else if (type.equals("B")){ pizza=new PizzaB(); } return pizza; }}
public class SimplePizzaFactory {
public static IPizza createPizza(String type){
IPizza pizza=null;
if(type.equals("A")){
pizza =new PizzaA();
}else if (type.equals("B")){
pizza=new PizzaB();
客户端:
public class Client { public static void main(String[] args) { IPizza pizza = SimplePizzaFactory.createPizza("A"); // 创建pizza之后的工作 pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); }}
public class Client {
public static void main(String[] args) {
IPizza pizza = SimplePizzaFactory.createPizza("A");
// 创建pizza之后的工作
优点:
缺点:
简单工厂模式虽然解决了产品对象的创建问题,但是仍然存在很大的设计问题:当添加新的产品时候,必须通过修改客户端传过去的类型参数,其次还需要修改工厂中的if-else逻辑,显然违反了开闭原则,此外简单工厂模式所有的产品都是同一个工厂所创,工厂类职责很重,违反了单一职责原则,因此将引出第二种工厂模式->工厂方法模式。
当添加新的产品时候,必须通过修改客户端传过去的类型参数,其次还需要修改工厂中的if-else逻辑,显然违反了开闭原则,此外简单工厂模式所有的产品都是同一个工厂所创,工厂类职责很重,违反了单一职责原则
不再提供一个统一的工厂类来创建所有的产品对象,而是针对不同的产品提供不同的工厂,系统提供一个与产品等级结构对应的工厂等级结构,工厂方法模式定义如下:
不再提供一个统一的工厂类来创建所有的产品对象,而是针对不同的产品提供不同的工厂,系统提供一个与产品等级结构对应的工厂等级结构
工厂方法模式(Factory Method Pattern):定义一个用于创建对象的接口,让子类决定将哪一个类实例化。工厂方法模式让一个类的实例化延迟到其子类。工厂方法模式又简称为工厂模式(Factory Pattern),又可称作虚拟构造器模式(Virtual Constructor Pattern)或多态工厂模式(Polymorphic Factory Pattern)。工厂方法模式是一种类创建型模式。
ProductB(具体产品)
Factory(抽象工厂)
ProductAFactory(具体工厂)
结构如图:
代码如下:
public interface Pizza { // 准备 void prepare(); // 烘烤 void bake(); // 切 void cut(); // 装盒 void box();}
public interface Pizza {
// 准备
// 烘烤
// 切
// 装盒
具体产品角色:
public class PizzaA implements Pizza { @Override public void prepare() { System.out.println("pizzaA开始准备"); } @Override public void bake() { System.out.println("pizzaA开始烘烤"); } @Override public void cut() { System.out.println("pizzaA开始切"); } @Override public void box() { System.out.println("pizzaA开始装盒"); }}
public class PizzaA implements Pizza {
System.out.println("pizzaA开始准备");
System.out.println("pizzaA开始烘烤");
System.out.println("pizzaA开始切");
System.out.println("pizzaA开始装盒");
public class PizzaB implements Pizza { @Override public void prepare() { System.out.println("pizzaB开始准备"); } @Override public void bake() { System.out.println("pizzaB开始烘烤"); } @Override public void cut() { System.out.println("pizzaB开始切"); } @Override public void box() { System.out.println("pizzaB开始装盒"); }}
public class PizzaB implements Pizza {
System.out.println("pizzaB开始准备");
System.out.println("pizzaB开始烘烤");
System.out.println("pizzaB开始切");
System.out.println("pizzaB开始装盒");
抽象工厂:
public interface PizzaFactory { Pizza createPizza();}
public interface PizzaFactory {
Pizza createPizza();
具体工厂角色:
public class PizzaAFactory implements PizzaFactory { @Override public Pizza createPizza() { return new PizzaA(); }}
public class PizzaAFactory implements PizzaFactory {
public Pizza createPizza() {
return new PizzaA();
public class PizzaBFactory implements PizzaFactory { @Override public Pizza createPizza() { return new PizzaB(); }}
public class PizzaBFactory implements PizzaFactory {
return new PizzaB();
public class Client { public static void main(String[] args) { // 针对抽象编程 PizzaAFactory可根据DI(依赖注入)进去 // 整个客户端就不需要对修改变化,全部是针对抽象编程 PizzaFactory factory = new PizzaAFactory(); Pizza pizza = factory.createPizza(); pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); }}
// 针对抽象编程 PizzaAFactory可根据DI(依赖注入)进去
// 整个客户端就不需要对修改变化,全部是针对抽象编程
PizzaFactory factory = new PizzaAFactory();
Pizza pizza = factory.createPizza();
工厂方法通过引入工厂等级结构,解决简单工厂职责过重(所有的产品都在一个工厂里产生)的问题,但是工厂方法会额外产生大量的工厂类,ProductA、ProductB、ProductC........,会给系统带来很大的开销,因此我们可以将相同类型的产品组成产品族,由同一个工厂生产,即抽象工厂模式的核心。
将相同类型的产品组成产品族,由同一个工厂生产
抽象工厂模式为创建一组对象提供了解决方案,与工厂方法模式相比,抽象工厂模式中的工厂负责创建一组,其定义如下:
抽象工厂模式(Abstract Factory Pattern):提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。抽象工厂模式又称为Kit模式,它是一种对象创建型模式。
场景如下:为了保证客户的实用安全,确保原料一致,所以需要一个工厂来生产原料,即此工厂负责原料家族中的每种原料,即工厂需要生产面团、酱料、芝士等,但是不同区域的风味不一致,抽象工厂模式设计如下图:
AbstractFactory(抽象工厂角色):
//原料生产工厂 每个区域的原料工厂都需要实现此接口public abstract class PizzaIngredientFactory { //每个原料都有一个对应的方法创建该原料 // 生产面团 abstract Dough createDough(); // 生产酱 abstract Sauce createSauce();}
//原料生产工厂 每个区域的原料工厂都需要实现此接口
public abstract class PizzaIngredientFactory {
//每个原料都有一个对应的方法创建该原料
// 生产面团
abstract Dough createDough();
// 生产酱
abstract Sauce createSauce();
具体工厂:纽约原料加工厂
// 纽约原料工厂public class NYPizzaIngredientFactory extends PizzaIngredientFactory { @Override Dough createDough() { return new DoughA(); } @Override Sauce createSauce() { return new SauceA(); }}
// 纽约原料工厂
public class NYPizzaIngredientFactory extends PizzaIngredientFactory {
Dough createDough() {
return new DoughA();
Sauce createSauce() {
return new SauceA();
具体工厂:中国原料加工厂
// 中国原料工厂public class ChinaIngredientFactory extends PizzaIngredientFactory { @Override Dough createDough() { return new DoughB(); } @Override Sauce createSauce() { return new SauceB(); }}
// 中国原料工厂
public class ChinaIngredientFactory extends PizzaIngredientFactory {
return new DoughB();
return new SauceB();
抽象产品角色:面团
// 面团public interface Dough {}
// 面团
public interface Dough {
抽象产品角色:酱料
// 酱料public interface Sauce {}
// 酱料
public interface Sauce {
具体产品角色:面团A
public class DoughA implements Dough{}
public class DoughA implements Dough{
具体产品角色:面团B
public class DoughB implements Dough{}
public class DoughB implements Dough{
具体产品角色:酱料A
public class SauceA implements Sauce {}
public class SauceA implements Sauce {
具体产品角色:酱料B
public class SauceB implements Sauce {}
public class SauceB implements Sauce {
我们可以发现要是在增加新的产品族很方便,只需要扩展新的具体工厂,但是要扩展产品的等级结构(在抽象工厂中加入新的原料),会发现完全违背开闭原则,修改量巨大。
先来回顾一下这三者的结构图:
简单工厂模式:
工厂方法模式:
简单工厂模式VS工厂方法模式
工厂方法模式VS抽象工厂模式
本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728