当前位置: 移动技术网 > IT编程>软件设计>设计模式 > 设计模式之工厂模式(上篇)

设计模式之工厂模式(上篇)

2019年08月08日  | 移动技术网IT编程  | 我要评论

为了面向接口编程,而不是面向实现编程,所以此时我么就不能再直接使用new了,因

为当看到“new”时,我们就会想到“具体”。

下面来看一个例子,假如你有一个披萨店,你的代码可能这么写:

 1     pizza orderpizza(){
 2         pizza pizza = new pizza();
 3         
 4         pizza.prepare();
 5         pizza.bake();
 6         pizza.cut();
 7         pizza.box();
 8         
 9         return pizza;
10     }

但是此时你需要更多披萨类型,所以你就要修改代码,如下所示:

 1     pizza orderpizza(string type){
 2         pizza pizza = new pizza();
 3 
 4         if (type.equals("cheese")) {
 5             pizza = new cheesepizza();
 6         } else if (type.equals("pepperoni")) {
 7             pizza = new pepperonipizza();
 8         } else if (type.equals("clam")) {
 9             pizza = new clampizza();
10         } else if (type.equals("veggie")) {
11             pizza = new veggiepizza();
12         }
13 
14         pizza.prepare();
15         pizza.bake();
16         pizza.cut();
17         pizza.box();
18 
19         return pizza;
20     }

但是此时由于产业竞争问题,你想加入一些其他口味的pizza或者删除某几种pizza,那么

你就不得不修改orderpizza(string type)里的4-12行,所以随着时间的推移,这个类就必

须一改再改,这毫无疑问是不好的!所以我们现在来把创建对象的代码封装起来,如下所

示:

 

这时我们称这个新对象(simplepizzafactory)为“工厂”,用来处理创建对象的细节。

现在让我们创建一个简单的披萨工厂:

先从工厂本身开始,封装创建对象的代码(simplepizzafactory.java)

 

 1 public class simplepizzafactory {
 2     public pizza createpizza(string type) {
 3         pizza pizza = null;
 4 
 5         if (type.equals("cheese")) {
 6             pizza = new cheesepizza();
 7         } else if (type.equals("pepperoni")) {
 8             pizza = new pepperonipizza();
 9         } else if (type.equals("clam")) {
10             pizza = new clampizza();
11         } else if (type.equals("veggie")) {
12             pizza = new veggiepizza();
13         }
14         return pizza;
15     }
16 }

 

重做pizzastore(pizzastore.java):

 1 public class pizzastore {
 2     simplepizzafactory factory;
 3 
 4     public pizzastore(simplepizzafactory factory) {
 5         this.factory = factory;
 6     }
 7 
 8     public pizza orderpizza(string type) {
 9         pizza pizza;
10 
11         pizza = factory.createpizza(type);
12 
13         pizza.prepare();
14         pizza.bake();
15         pizza.cut();
16         pizza.box();
17 
18         return pizza;
19     }
20 }

测试类(main.java):

 1 public class main {
 2 
 3     public static void main(string[] args) {
 4         simplepizzafactory factory = new simplepizzafactory();
 5         pizzastore store = new pizzastore(factory);
 6 
 7         pizza pizza = store.orderpizza("cheese");
 8         system.out.println("we ordered a " + pizza.getname() + "\n");
 9         system.out.println(pizza);
10 
11         pizza = store.orderpizza("veggie");
12         system.out.println("we ordered a " + pizza.getname() + "\n");
13         system.out.println(pizza);
14     }
15 }

结果展示:

好啦,这个示例完成了,这个其实叫做简单工厂,他其实不是一个设计模式,而更像是一

种编程习惯。这里只列举了这个项目的关键代码,至于这个简单工厂的完整代码,读者可

到:https://github.com/stray-kite/design-pattern/tree/master/src/headfirst/designpatterns/factory/pizzas

下载

 

好了,下载聊完了简单工厂,那么让我们进入正题,聊一聊两个重量级的模式,他们都是

工厂!

 

现在我们要建立几个加盟店。

有了这个图,你开始有一个想法啦,那就是:

 

1 nypizzafactory nyfactory = new nypizzafactory();
2 pizzastore nystore = new pizzastore(nyfactory);
3 nystore.orderpizza("veggie");
4 
5 chicagepizzafactory chicagefactory = new chicagepizzafactory();
6 pizzastore chicagestore = new pizzastore(chicagofactory);
7 chicagostore.orderpizza("veggie");

 

但是,你想要多一些质量控制:在推广simplefactory时,你发现加盟店的确是采用你的工

厂创建披萨,但是其他部分,却开始采用他们自创的流程:烘烤的做法有些差异、不要切片

、使用其他厂商的盒子。

再想想这个问题,你真的希望能够建立一个框架,把加盟店和创建披萨捆绑在一起的同时又

保持一定的弹性。

 

所以开始使用框架啦:

首先,看看pizzastore(pizzastore.java)所做的改变;喔嚯,变成抽象的了,也就是把创

建对象的工作移交给子类做决定了:

 1 public abstract class pizzastore {
 2     abstract pizza createpizza(string item);
 3 
 4     public pizza orderpizza(string type) {
 5         pizza pizza = createpizza(type);
 6         system.out.println("--- making a " + pizza.getname() + " ---");
 7         pizza.prepare();
 8         pizza.bake();
 9         pizza.cut();
10         pizza.box();
11         return pizza;
12     }
13 }

接下来,轮到子类给pizzastore做决定了!(nypizzastore.java和chicagepizzastore.java

,这是两个披萨店):

 1 public class chicagopizzastore extends pizzastore {
 2     pizza createpizza(string item) {
 3         if (item.equals("cheese")) {
 4             return new chicagostylecheesepizza();
 5         } else if (item.equals("veggie")) {
 6             return new chicagostyleveggiepizza();
 7         } else if (item.equals("clam")) {
 8             return new chicagostyleclampizza();
 9         } else if (item.equals("pepperoni")) {
10             return new chicagostylepepperonipizza();
11         } else return null;
12     }
13 }
 1 public class nypizzastore extends pizzastore{
 2     pizza createpizza(string item) {
 3         if (item.equals("cheese")) {
 4             return new nystylecheesepizza();
 5         } else if (item.equals("veggie")) {
 6             return new nystyleveggiepizza();
 7         } else if (item.equals("clam")) {
 8             return new nystyleclampizza();
 9         } else if (item.equals("pepperoni")) {
10             return new nystylepepperonipizza();
11         } else return null;
12     }
13 }

差点忘记了,我们还得写一个比萨本身(pizza.java):

 1 import java.util.arraylist;
 2 
 3 public abstract class pizza {
 4     string name;
 5     string dough;
 6     string sauce;
 7     arraylist<string> toppings = new arraylist<string>();
 8 
 9     void prepare() {
10         system.out.println("prepare " + name);
11         system.out.println("tossing dough...");
12         system.out.println("adding sauce...");
13         system.out.println("adding toppings: ");
14         for (string topping : toppings) {
15             system.out.println("   " + topping);
16         }
17     }
18 
19     void bake() {
20         system.out.println("bake for 25 minutes at 350");
21     }
22 
23     void cut() {
24         system.out.println("cut the pizza into diagonal slices");
25     }
26 
27     void box() {
28         system.out.println("place pizza in official pizzastore box");
29     }
30 
31     public string getname() {
32         return name;
33     }
34 
35     public string tostring() {
36         stringbuffer display = new stringbuffer();
37         display.append("---- " + name + " ----\n");
38         display.append(dough + "\n");
39         display.append(sauce + "\n");
40         for (string topping : toppings) {
41             display.append(topping + "\n");
42         }
43         return display.tostring();
44     }
45 }

然后还剩下,一些具体的子类:定义两个不同的店的芝士披萨

nystylecheesepizza.java:

1 public class nystylecheesepizza extends pizza {
2     public nystylecheesepizza() {
3         name = "ny style sauce and cheese pizza";
4         dough = "thin crust dough";
5         sauce = "marinara sauce";
6 
7         toppings.add("grated reggiano cheese");
8     }
9 }

chicagostylecheesepizza.java:

 1 public class chicagostylecheesepizza extends pizza {
 2     public chicagostylecheesepizza() {
 3         name = "chicago style deep dish cheese pizza";
 4         dough = "extra thick crust dough";
 5         sauce = "plum tomato sauce";
 6 
 7         toppings.add("shredded mozzarella cheese");
 8     }
 9 
10     void cut() {
11         system.out.println("cutting the pizza into square slices");
12     }
13 }

 

最后来一组测试类(main.java):

 1 public class main {
 2 
 3     public static void main(string[] args) {
 4         pizzastore nystore = new nypizzastore();
 5         pizzastore chicagostore = new chicagopizzastore();
 6 
 7         pizza pizza = nystore.orderpizza("cheese");
 8         system.out.println("ethan ordered a " + pizza.getname() + "\n");
 9 
10         pizza = chicagostore.orderpizza("cheese");
11         system.out.println("joel ordered a " + pizza.getname() + "\n");
12 
13         pizza = nystore.orderpizza("clam");
14         system.out.println("ethan ordered a " + pizza.getname() + "\n");
15 
16         pizza = chicagostore.orderpizza("clam");
17         system.out.println("joel ordered a " + pizza.getname() + "\n");
18 
19         pizza = nystore.orderpizza("pepperoni");
20         system.out.println("ethan ordered a " + pizza.getname() + "\n");
21 
22         pizza = chicagostore.orderpizza("pepperoni");
23         system.out.println("joel ordered a " + pizza.getname() + "\n");
24 
25         pizza = nystore.orderpizza("veggie");
26         system.out.println("ethan ordered a " + pizza.getname() + "\n");
27 
28         pizza = chicagostore.orderpizza("veggie");
29         system.out.println("joel ordered a " + pizza.getname() + "\n");
30     }
31 }

 

结果展示(部分结果)

 

此段代码地址:

          https://github.com/stray-kite/design-pattern/tree/master/src/headfirst/designpatterns/factory/pizzafm

好了,现在然我们看一下工厂模式的定义吧!

工厂模式:定义一个创建对象的接口,但由子类决定要实例化的是哪一个。工厂方法让类把

实例化推迟到了子类。

重点:简单工厂和工厂方法的区别:

                 子类的确看起来很像简单工厂。简单工程把全部的事情,在一个地方都处理完了,然而工厂方

          法却是创建了一个框架,让子类决定要如何实现。比方说,在工厂方法中,orderpizza()方法提供了

          一个一般的框架,以便创建披萨,orderpizza()方法依赖工厂方法创建具体类,并制造出实际的披萨

          。可通过继承pizzastore()类,决定实际制造出的披萨是什么。简单工厂的做法,可以将对象创建封

          装起来,但是简单工厂不具备工厂方法的弹性,因为简单工程不能变更正在创建的产品。

未完待续......

 

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网