HeadFirst 设计模式 - Chapte4 工厂设计模式

Author Avatar
thychan Nov 09, 2016
  • Read this article on other devices

工厂模式

定义

img

工厂方法模式定义了一个创建对象的接口,但由子类决定(“决定”是指在编写创建者类creator类时,不需要知道实际创建的product是哪一个。选择使用了哪个子类,自然就决定了实际创建的产品是什么)要实例化的类是哪一个。
工厂方法让类把实例化推迟到子类。ConcreteCreator负责创建一个或多个具体产品,只有ConcreteCreator类知道如何创建这些产品(组合使用了ConcreteProduct)。

img

简单工厂模式是让一个对象负责所有具体类的实例化,而工厂模式是让一群子类(NYStylePizzaStore, ChicagoStylePizzaStore)来负责实例化。工厂方法 createPizza()是抽象的,所以会依赖子类来处理对象的创建 — 工厂模式通过让子类决定该创建的对象是什么,来达到将对象创建的过程封装的目的。


Creator:

PizzaStore实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public abstract class PizzaStore {
public final Pizza orderPizza(String type) // order system
{
Pizza pizza;
pizza = createPizza(type);
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
abstract Pizza createPizza(String type); // factory method
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class ChicagoPizzaStore extends PizzaStore {
Pizza pizza = null;
@Override
Pizza createPizza(String type) {
if(type.equals("cheese")){
pizza = new ChicagoStyleCheesePizza(); // create specific class
}else if(type.equals("pepperoni")){
pizza = new NYStylePepperoniPizza(); // create specific class
}else if (type.equals("clam")){
pizza = new NYStyleClamPizza(); // create specific class
}else if (type.equals("veggie")){
pizza = new NYStyleVeggiePizza(); // create specific class
}
return pizza;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class NYPizzaStore extends PizzaStore {
Pizza pizza = null;
@Override
Pizza createPizza(String type) {
if(type.equals("cheese")){
pizza = new NYStyleCheesePizza(); // create specific class
}else if(type.equals("pepperoni")){
pizza = new NYStylePepperoniPizza(); // create specific class
}else if (type.equals("clam")){
pizza = new NYStyleClamPizza(); // create specific class
}else if (type.equals("veggie")){
pizza = new NYStyleVeggiePizza(); // create specific class
}
return pizza;
}
}

Products:

Pizza的实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import java.util.*;
public abstract class Pizza {
String name;
String dough;
String sauce;
ArrayList<String> toppings = new ArrayList<String>();
public 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));
}
}
public void bake(){
System.out.println("Bake for 25 mins at 350");
}
public void cut(){
System.out.println("Cutting the pizza into diagonal slics");
}
public void box(){
System.out.println("Place pizza in official PizzaStore box");
}
public String getName(){
return name;
}
}
1
2
3
4
5
6
7
8
public class NYStyleCheesePizza extends Pizza{
public NYStyleCheesePizza(){
name = "NY Style Sauce and Cheese Pizza";
dough = "Thin Crust Dough";
sauce = "Marinara Sauce";
toppings.add("Grated Regginao Cheese");
}
}

测试类

1
2
3
4
5
6
7
8
9
10
11
public class PizzaTestDrive {
public static void main(String[] args){
// create two stores
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");
}
}

抽象工厂模式

定义

抽象工厂模式提供一个接口,用于创建相关或依赖对象的家族(使用抽象的接口来创建一组相关的产品),而不需要明确指定具体类。

这个接口内的每个方法都负责创建一个具体的产品,同时我们利用实现抽象工厂的子类来提供这些具体的做法。

img

好处

创建产品家族 + 将相关产品集合起来。

具体实现 AbstractFactory接口创建一个产品家族

1
2
3
4
5
6
7
8
public interface PizzaIngredientFactory {
public Dough createDough();
public Sause createSauce();
public Cheese createCheese();
public Veggies[] createVeggies();
public Pepperoni createPepperoni();
public Clams createClam();
}

具体工厂实现不同的产品家族。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class NYPizzaIngredientFactory implements PizzaIngredientFactory {
public Cheese createCheese() {
return new ReggianoCheese();
}
public Clams createClam() {
return new FreshClams();
}
public Dough createDough() {
return new ThinCrustDough();
}
public Pepperoni createPepperoni() {
return new SlicedPepperoni();
}
public Sause createSauce() {
return new MarinaraSauce();
}
public Veggies[] createVeggies() {
Veggies veggies[] = {
new Garlic(), new Onion(),new Mushroom(),new RedPepper()
};
return veggies;
}
}

抽象的产品 Pizza接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public abstract class Pizza {
String name;
Dough dough;
Sause sauce;
Veggies veggies[];
Cheese cheese;
Pepperoni pepproni;
Clams clam;
abstract public void prepare();
public void bake(){
System.out.println("Bake for 25 mins at 350");
}
public void cut(){
System.out.println("Cutting the pizza into diagonal slics");
}
public void box(){
System.out.println("Place pizza in official PizzaStore box");
}
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
}

具体的产品CheesePizza:使用了(组合)抽象工厂生产的一组产品,集合起来的产品为CheesePizza

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class CheesePizza extends Pizza {
PizzaIngredientFactory ingredientFactory; // 要制作pizza,需要提供原料,所以每个pizza都需要从构造器参数得到一个工厂
public CheesePizza(PizzaIngredientFactory ingredientFactory){
this.ingredientFactory = ingredientFactory;
}
@Override
public void prepare() {
System.out.println("Preparing "+name);
dough = ingredientFactory.createDough();
sauce = ingredientFactory.createSauce();
cheese = ingredientFactory.createCheese();
}
}

客户的代码只需要涉及抽象工厂

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class NYPizzaStore extends PizzaStore {
Pizza createPizza(String item){
Pizza pizza = null;
PizzaIngredientFactory ingredientFactory = new NYPizzaIngredientFactory();
if(item.equals("cheese"))
{
pizza = new CheesePizza(ingredientFactory);
pizza.setName("New York style cheese pizza");
}
else if (item.equals("veggie")) {
pizza = new VeggiePizza(ingredientFactory);
pizza.setName("New York style veggie pizza");
}
return pizza;
}
}

工厂模式 VS 抽象工厂模式

都负责封装对象的创建。都能将对象的创建封装起来,将应用程序解耦,并降低对其特定实现的依赖。

工厂模式使用的是类,通过继承,即利用工厂方法创建对象,需要扩展一个类,并覆盖它的工厂方法。

1
工厂模式提供一个抽象的接口来创建一个产品,由每个子类决定实例化哪个具体的产品(具体类)

而抽象工厂模式使用的是对象,使用组合。即提供一个用来创建一个产品家族的抽象类型,这个类型的子类定义了产品被产生的方法。要使用这个工厂,必须先实例化它,然后将它传入一些针对抽象类型所写的代码里。

1
抽象工厂模式提供一个抽象接口来创建一个产品家族,每个具体子类都创建一个家族产品。

注:该文章转载自:https://segmentfault.com/u/secondlife/articles