设计模式之工厂方法模式(FACTORY METHOD)问题模拟工厂方法模式分析依赖倒置原则小结

工厂方法模式定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。 我们依然接着简单工厂模式提出的披萨店问题继续探讨

问题模拟

我们假设有多种不同的pizza店,比如纽约的pizza点,芝加哥的pizza店,他们都有自己制作的不同种类的pizza。 如果我们采用简单模式方法,那么我们就需要分别建立纽约pizzafactory和芝加哥的factory等等工厂,但这样做没有弹性。我们能不能将制作pizza的行为局限在旁pizzaStore类中,但同时又能让不同类的点去各自实例化自己的pizza类。 显然,我们可以将pizzaStore由一个具体类,变为一个抽象的接口:

public abstract class PizzaStore {
    public Pizza orderPizza(String type) {
      Pizza pizza;
      pizza=createPizza(type);
      pizza.prepare();
      pizza.bake();
      pizza.cut();
      pizza.box();
      return pizza;
  }
  abstract Pizza createPizza(String type);
}

Paste_Image.png

定义了一个抽象的基类,里面有个抽象的create方法,我们让其他的纽约地区,芝加哥地区等等不同的继承自这个基类,让子类自己决定怎么创建pizza。

public class NYPizzaStore extends PizzaStore {
Pizza createPizza(String item) {
if (item.equals(“cheese”)) {
return new NYStyleCheesePizza();
} else if (item.equals(“veggie”)) {
return new NYStyleVeggiePizza();
} else if (item.equals(“clam”)) {
return new NYStyleClamPizza();
} else if (item.equals(“pepperoni”)) {
return new NYStylePepperoniPizza();
} else return null;
}
}

以上是我们实现的一个具体的纽约pizzastore类。他继承实现了基类的抽象方法。

然后我们继承实现抽象的pizza类和具体的pizza类

public abstract class Pizza {
String name;
String dough;
String sauce;
ArrayList toppings = new ArrayList();
void prepare() {
System.out.println(“Preparing “ + name);
System.out.println(“Tossing dough...”);
System.out.println(“Adding sauce...”);
System.out.println(“Adding toppings: “);
for (int i = 0; i < toppings.size(); i++) {
System.out.println(“ “ + toppings.get(i));
}
}
void bake() {
System.out.println(“Bake for 25 minutes at 350”);
}
void cut() {
System.out.println(“Cutting the pizza into diagonal slices”);
}
void box() {
System.out.println(“Place pizza in official PizzaStore box”);
}
public String getName() {
return name;
}
}

具体的产品类

public class NYStyleCheesePizza extends Pizza {
public NYStyleCheesePizza() {
name = “NY Style Sauce and Cheese Pizza”;
dough = “Thin Crust Dough”;
sauce = “Marinara Sauce”;
toppings.add(“Grated Reggiano Cheese”);
}
}
public class NYStyleCheesePizza extends Pizza {
public NYStyleCheesePizza() {
name = “NY Style Sauce and Cheese Pizza”;
dough = “Thin Crust Dough”;
sauce = “Marinara Sauce”;
toppings.add(“Grated Reggiano Cheese”);
}
}

public class ChicagoStyleCheesePizza extends Pizza {
public ChicagoStyleCheesePizza() {
name = “Chicago Style Deep Dish Cheese Pizza”;
dough = “Extra Thick Crust Dough”;
sauce = “Plum Tomato Sauce”;
toppings.add(“Shredded Mozzarella Cheese”);
}
void cut() {
System.out.println(“Cutting the pizza into square slices”);
}
}

最后测试我们的代码:

public class PizzaTestDrive {
public static void main(String[] args) {
PizzaStore nyStore = new NYPizzaStore();
PizzaStore chicagoStore = new ChicagoPizzaStore();
Pizza pizza = nyStore.orderPizza(“cheese”);
System.out.println(“Ethan ordered a “ + pizza.getName() + “\n”);
pizza = chicagoStore.orderPizza(“cheese”);
System.out.println(“Joel ordered a “ + pizza.getName() + “\n”);
}
}

工厂方法模式分析

Paste_Image.png

工厂方法模式常常分为两大类:一个创建产品的创建类,一个产品类,其中创建类定义一个抽象的接口,外加其余的继承自他的具体实现。产品类也是类似,定义一个抽象的产品类接口,具体的产品类实现继承自基类。

Paste_Image.png

Paste_Image.png

把创建对象的代码集中在一个对象或者方法中,可以避免代码的重复,并且更方便的以后的维护,这意味着客户在实例化对象的时候,依赖的是接口,而不是具体的对象,而正是我们之前提到的具体设计原则中的一种,针对接口编程。

依赖倒置原则

这是我们提出的又一设计原则:**要依赖抽象,不要依赖具体实现 ** 工厂方法模式中,就很好的应用这个原则: 如果我们采用简单工厂模式,依赖关系是这样的:

Paste_Image.png

而采用工厂方法模式,依赖关系如图:

Paste_Image.png

这就是依赖倒置原则,高层组件依赖了底层的pizza组件!

小结

工厂方法模式对简单工厂模式进行了抽象。有一个抽象的Factory类(可以是抽象类和接口),这个类将不再负责具体的产品生产,而是只制定一些规范,具体的生产工作由其子类去完成。在这个模式中,工厂类和产品类往往可以依次对应。即一个抽象工厂对应一个抽象产品,一个具体工厂对应一个具体产品,这个具体的工厂就负责生产对应的产品。

工厂方法经常用在以下两种情况中:

  • 第一种情况是对于某个产品,调用者清楚地知道应该使用哪个具体工厂服务,实例化该具体工厂,生产出具体的产品来。Java Collection中的iterator() 方法即属于这种情况。
  • 第二种情况,只是需要一种产品,而不想知道也不需要知道究竟是哪个工厂为生产的,即最终选用哪个具体工厂的决定权在生产者一方,它们根据当前系统的情况来实例化一个具体的工厂返回给使用者,而这个决策过程这对于使用者来说是透明的。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏zhisheng

运算优先级、结合性、求值顺序、副作用和顺序点

标题中这几个概念,是很多C/C++程序员在表达式上容易出问题或不清楚的地方,虽然这些概念在很多语言都有体现,但C里面特别明显,所以就以C语言为例子总结下 运算...

4687
来自专栏每日一篇技术文章

Swift3.0 - 探究Self的用途

893
来自专栏小詹同学

Leetcode打卡 | No.23 合并 k 个有序链表

欢迎和小詹一起定期刷leetcode,每周一和周五更新一题,每一题都吃透,欢迎一题多解,寻找最优解!这个记录帖哪怕只有一个读者,小詹也会坚持刷下去的!

1341
来自专栏Android机动车

设计模式——工厂方法模式

工厂方法模式,又称工厂模式、多态工厂模式和虚拟构造器模式,通过定义工厂父类负责定义创建对象的公共接口,而子类则负责生成具体的对象。

802
来自专栏菜鸟前端工程师

JavaScript学习笔记021-常用排序算法

612
来自专栏程序员互动联盟

【编程基础】C++ Primer快速入门五:实用的模板库

除上篇博客介绍的基本数据类型外,C++ 还定义了一个内容丰富的抽象数据类 型标准库。包括 string 和 vector,它们分别定义了字符串和矢量(集合)。s...

2935
来自专栏非著名程序员

鸡蛋问题来了,是先有Class还是先有Object?

周末比较无聊,在浏览论坛的时候,偶然看到一个程序猿提问的问题,他时这样提问的:突然想到一个很菜的问题, 倒底先有Object还是先有Class?所有类都是Obj...

2036
来自专栏WD学习记录

Python数据结构与算法笔记(3)

递归是一种解决问题的方法,将问题分解为更小的子问题,直到得到一个足够小的问题可以被很简单地解决,通常递归设计函数调用自身。递归允许我们编写优雅的解决方案,解决可...

1251
来自专栏算法channel

一道伤脑筋的算法题 亮了

一个数组,求除了某元素自身位置之外的其他元素累积相乘,返回一个同长度的数组。有两个要求比较苛刻: 1) 不能用除法 2) 时间复杂度O(n),空间复杂度O(1)...

760
来自专栏编码前线

关于三种工厂模式的总结

工厂模式分为简单工厂模式,工厂方法模式和抽象工厂模式,它们都属于设计模式中的创建型模式。其主要功能都是帮助我们把对象的实例化部分抽取了出来,目的是降低系统中代...

1071

扫码关注云+社区

领取腾讯云代金券