第一節:不使用設計模式的傳統方式
阿新 • • 發佈:2021-01-03
一、提出需求
分析一個關於生產披薩的專案:要便於披薩種類的擴充套件,要便於維護。
(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物件的程式碼就不需要修改了。