生活中的工厂模式
1、您需要一辆汽车,可以直接从工厂里面提货,而不用去管这辆汽车是怎么做出来的,以及这个汽车里面的具体实现。
2、玩具店里需要一些坦克玩具,就需要从玩具厂商那边进货,不需要知道这些坦克玩具的制造过程。
工厂方法模式
工厂方法模式定义了一个创建对象的接口(创建一个对象),但是由子类决定要实例化哪个类。工厂方法让类把实例化推迟到子类。
工厂方法模式的类图如下。(下图来自于《Head First 设计模式》)
在《Head First 设计模式》中,它举例了在美国不同的城市生产出来的披萨,其每个州的披萨工厂都有着一套的制作步骤被封装起来,比如“准备”、“烘烤”、“切” 和 “包装”。然后每个州的生产的披萨交给具体的工厂类来实现。
这是抽取出 Pizza 共有的属性和制作步骤。
package com.example.demo_springboot.designpattern.factory;
import java.util.ArrayList;
import java.util.List;
public abstract class Pizza {
String name; // 名称
String dough; // 面团类型
String sauce; // 馅料
List<String> toppings = new ArrayList<>();
public void prepare() {
System.out.println("准备:" + name);
System.out.println("扔面团...");
System.out.println("添加馅料...");
}
public void bake() {
System.out.println("烤25分钟");
}
public void cut() {
System.out.println("切披萨");
}
public void box() {
System.out.println("包装披萨");
}
public String getName() {
return name;
}
}
Pizza 的具体实现,芝加哥 Pizza 和 纽约 Pizza。
纽约披萨。
package com.example.demo_springboot.designpattern.factory;
public class NewYorkStyleCheesePizza extends Pizza {
public NewYorkStyleCheesePizza() {
name = "纽约风味的奶酪披萨";
dough = "薄皮面团";
sauce = "大蒜番茄酱";
toppings.add("磨碎的雷吉亚诺奶酪");
}
}
芝加哥披萨。
package com.example.demo_springboot.designpattern.factory;
public class ChicagoStyleCheesePizza extends Pizza {
public ChicagoStyleCheesePizza() {
name = "芝加哥风味深盘奶酪披萨";
dough = "Extra Thick Crust Dough";
sauce = "Plum Tomato Sauce";
}
@Override
public void cut() {
System.out.println("切成正方形");
}
}
然后这些披萨需要交给各个城市的工厂,每个州的披萨工厂都有着一套的制作步骤,所以将步骤封装到抽象类当中。
package com.example.demo_springboot.designpattern.factory;
public abstract class PizzaStore {
public Pizza orderPizza(String type) {
Pizza pizza = createPizza(type);
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
protected abstract Pizza createPizza(String pizza);
}
芝加哥的披萨工厂(注意:类的实例化推迟到子类了)。
public class ChicagoPizzaStore extends PizzaStore {
@Override
protected Pizza createPizza(String pizza) {
if("cheese".equals(pizza)) {
return new ChicagoStyleCheesePizza();
}
return null;
}
}
纽约的披萨工厂(注意:类的实例化推迟到子类了)。
package com.example.demo_springboot.designpattern.factory;
public class NewYorkPizzaStore extends PizzaStore {
@Override
public Pizza createPizza(String pizza) {
if("cheese".equals(pizza)) {
return new NewYorkStyleCheesePizza();
}
return null;
}
}
接下来,在不同城市生产不同的披萨。
package com.example.demo_springboot.designpattern.factory;
public class PizzaTest {
public static void main(String[] args) {
PizzaStore pizzaStore = new NewYorkPizzaStore();
Pizza pizza = pizzaStore.orderPizza("cheese");
System.out.println("A 订购了一个:" + pizza.getName() + "\n");
pizzaStore = new ChicagoPizzaStore();
pizza = pizzaStore.orderPizza("cheese");
System.out.println("B 订购了一个:" + pizza.getName() + "\n");
}
}
运行一下:
准备:纽约风味的奶酪披萨
扔面团...
添加馅料...
烤25分钟
切披萨
包装披萨
A 订购了一个:纽约风味的奶酪披萨
准备:芝加哥风味深盘奶酪披萨
扔面团...
添加馅料...
烤25分钟
切成正方形
包装披萨
B 订购了一个:芝加哥风味深盘奶酪披萨
抽象工厂模式
抽象工厂模式提供了提供一个创建一系列相关(创建多个与之相关的)或者相互依赖对象的接口,而无需指定他们具体的类。
比如:去公司面试或者上班,肯定有两套或多套衣服吧,比如说有商务装(成套,一系列具体产品)、时尚装(成套,一系列具体产品),甚至对于一个家庭来说,可能有商务女装、商务男装、时尚女装、时尚男装,这些也都是成套的,即一系列具体产品。假设一种情况,在您的家中,某一个衣柜(具体工厂)只能存放某一种这样的衣服(成套,一系列具体产品),每次拿这种成套的衣服时也自然要从这个衣柜中取出了。
抽象工厂模式的类图如下所示。
站外例子
以下,是在菜鸟教程的一个很好的例子:
工厂模式
工厂模式也就是鼠标工厂是个父类,有生产鼠标这个接口。
戴尔鼠标工厂,惠普鼠标工厂继承它,可以分别生产戴尔鼠标,惠普鼠标。
生产哪种鼠标不再由参数决定,而是创建鼠标工厂时,由戴尔鼠标工厂创建。
后续直接调用**鼠标工厂.生产鼠标()**即可
抽象工厂模式
抽象工厂模式也就是不仅生产鼠标,同时生产键盘。
也就是 PC 厂商是个父类,有生产鼠标,生产键盘两个接口。
戴尔工厂,惠普工厂继承它,可以分别生产戴尔鼠标+戴尔键盘,和惠普鼠标+惠普键盘。
创建工厂时,由戴尔工厂创建。
后续**工厂.生产鼠标()则生产戴尔鼠标,工厂.生产键盘()**则生产戴尔键盘。
在抽象工厂模式中,假设我们需要增加一个工厂
假设我们增加华硕工厂,则我们需要增加华硕工厂,和戴尔工厂一样,继承 PC 厂商。
之后创建华硕鼠标,继承鼠标类。创建华硕键盘,继承键盘类即可。
在抽象工厂模式中,假设我们需要增加一个产品
假设我们增加耳麦这个产品,则首先我们需要增加耳麦这个父类,再加上戴尔耳麦,惠普耳麦这两个子类。
之后在PC厂商这个父类中,增加生产耳麦的接口。最后在戴尔工厂,惠普工厂这两个类中,分别实现生产戴尔耳麦,惠普耳麦的功能。 以上。
请勿发布违反中国大陆地区法律的言论,请勿人身攻击、谩骂、侮辱和煽动式的语言。