1. 程式人生 > 實用技巧 >第一節:不使用設計模式的傳統方式

第一節:不使用設計模式的傳統方式

一、提出需求

  分析一個關於生產披薩的專案:要便於披薩種類的擴充套件,要便於維護。

  (1)披薩的種類很多(比如:GreekPizza、CheesePizza 等)

  (2)披薩的製作有 prepare,bake,cut,box

  (3)完成披薩店訂購功能。

二、使用傳統的方式來完成

  思路分析:可以得到,將披薩做成一個抽象類,裡面宣告所有披薩都需要的功能,然後根據需要來繼承該類,再建立一個訂購類,可以根據使用者輸入的披薩名稱來生產不同種類的披薩。

  UML 類圖:

  

  Demo:不使用設計模式

  Pizza 相關類

 1 /**
 2  * 將 pizza 類做成抽象類
3 */ 4 public abstract class Pizza { 5 //名字 6 protected String name; 7 8 //準備原材料, 不同的披薩不一樣,因此,我們做成抽象方法 9 public abstract void prepare(); 10 11 //烘焙 12 public void bake() { 13 System.out.println(name + " baking;"); 14 } 15 16 //切割 17 public void cut() { 18
System.out.println(name + " cutting;"); 19 } 20 21 //打包 22 public void box() { 23 System.out.println(name + " boxing;"); 24 } 25 26 public void setName(String name) { 27 this.name = name; 28 } 29 30 } 31 32 public class GreekPizza extends Pizza{ 33 @Override
34 public void prepare() { 35 System.out.println(" 給希臘披薩 準備原材料 "); 36 } 37 } 38 39 public class CheesePizza extends Pizza { 40 @Override 41 public void prepare() { 42 System.out.println(" 給製作乳酪披薩 準備原材料 "); 43 } 44 }

訂購披薩

 1 public class OrderPizza {
 2 
 3     //構造器
 4     public OrderPizza() {
 5         Pizza pizza = null;
 6         String orderType; //訂購披薩的型別
 7         do {
 8             orderType = getType();
 9             if (orderType.equals("greek")) {
10                 pizza = new GreekPizza();
11                 pizza.setName("希臘披薩");
12             } else if (orderType.equals("cheese")) {
13                 pizza = new CheesePizza();
14                 pizza.setName("乳酪披薩");
15             } else {
16                 System.out.println("此類披薩還未上架");
17                 break;
18             }
19             //輸出披薩製作過程
20             pizza.prepare();
21             pizza.bake();
22             pizza.cut();
23             pizza.box();
24 
25         } while (true);
26     }
27 
28     //宣告一個方法,可以獲取客戶希望訂購的披薩種類
29     private String getType() {
30         try {
31             BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
32             System.out.println("input pizza 種類:");
33             String str = bufferedReader.readLine();
34             return str;
35         } catch (IOException e) {
36             e.printStackTrace();
37             return "";
38         }
39     }
40 }

測試類:

1 public class PizzaStore {
2 
3     public static void main(String[] args) {
4         new OrderPizza();
5     }
6 }

  效果:

  

  此時,我們需要另外上架一個新的 PepperPizza 披薩,對程式碼做出對應的修改。

  建立一個 PepperPizza 類:

1 public class PepperPizza extends Pizza {
2     @Override
3     public void prepare() {
4         // TODO Auto-generated method stub
5         System.out.println(" 給胡椒披薩準備原材料 ");
6     }
7 }

  對訂購披薩類進行修改:

 1 public OrderPizza() {
 2         Pizza pizza = null;
 3         String orderType; //訂購披薩的型別
 4         do {
 5             orderType = getType();
 6             if (orderType.equals("greek")) {
 7                 pizza = new GreekPizza();
 8                 pizza.setName("希臘披薩");
 9             } else if (orderType.equals("cheese")) {
10                 pizza = new CheesePizza();
11                 pizza.setName("乳酪披薩");
12             } else if (orderType.equals("pepper")) {
13                 pizza = new PepperPizza();
14                 pizza.setName("胡椒披薩");
15             } else {
16                 System.out.println("此類披薩還未上架");
17                 break;
18             }
19             //輸出披薩製作過程
20             pizza.prepare();
21             pizza.bake();
22             pizza.cut();
23             pizza.box();
24 
25         } while (true);
26     }

三、傳統的方式的優缺點

  1、優點是比較好理解,簡單易操作。

  2、缺點是違反了設計模式的 OCP 原則,即對擴充套件開發,對修改關閉。即當我們給類增加新功能的時候,儘量不修改程式碼,或者儘可能少修改程式碼。

  3、比如這時要新增一個 Pizza 的種類(Pepper披薩),需要做如下修改:

    ① 增加一個對應的 PepperPizza類;

    ② 凡是訂購 Pizza 的程式碼都需要修改;(可能有一處或者多處都使用)

    

  4、改進的思路分析

    分析:修改程式碼可以接受,但是如果我們在其他的地方也有建立 Pizza的程式碼,就意味著,也需要修改,而建立 Pizza 的程式碼,往往有多處。

    思路:把建立 Pizza 物件封裝到一個類中,這樣我們有新的 Pizza 種類時,只需要修改該類即可。其他有建立到Pizza物件的程式碼就不需要修改了。