工廠方法模式


1 工廠模式介紹

  1.1 定義:定義一個用於創建對象的接口,讓子類絕對實例化哪一個類,工廠方法使一個類的實例化延遲到其子類。

  工廠方法模式通用類圖:

  在工廠模式中,抽象產品類Product負責定義產品的共性,實現對事物最抽象的定義,Creator為抽象類創建類,也就是抽象工廠,具體如何創建產品類是有具體的實現工廠ConcreteCreator完成的。

  1.2 工廠方法模式的優點

  • 良好的封裝性,代碼結構清晰。
  • 擴展性非常優秀,在增加產品類的情況系下,只有適當的修改具體的工廠類或擴展一個工廠類,就可以“擁抱變化”。
  • 屏蔽產品類。產品類的實現如何變化,調用者無需關心,它只需關心產品的接口,只要接口保持不變,系統中的上層模塊就不需要發生變化。
  • 解耦框架。高層模塊只需要知道產品的抽象類,其他實現類都不用關心。

  1.3 工廠方法模式的使用場景

2 工廠模式實現

2.1 簡單工廠模式(靜態工廠模式)

  以實現一個計算器為例:

  整個過程涉及到三個對象,人(Program4類表示)、計算器(以OperationFactory類表示)、計算方式(計算方式中有多種,加減乘除等,但都屬於計算方法,以一個父類Operation,加減乘除繼承覆寫方法即可)。整個示例類如下圖:

 1 public class Program4 {
 2     public static void main(String[] args) {
 3         try {
 4             Scanner scanner = new Scanner (System.in);
 5 
 6             System.out.println ("請輸入數字A:");
 7             double numberA = Double.parseDouble (scanner.nextLine ());
 8             System.out.println ("選擇運算符(+、-、*、/):");
 9             String strOperate = scanner.nextLine ();
10             System.out.println ("請輸入數字B:");
11             double numberB = Double.parseDouble (scanner.nextLine ());
12             String strResult = "";
13 
14             if ( strOperate != "/" || numberB != 0){
15                 Operation oper;
16                 oper = OperationFactory.createOperate (strOperate);
17                 oper.setNumberA (numberA);
18                 oper.setNumberB (numberB);
19                 
20                 strResult = String.valueOf (oper.getResult ());
21                 System.out.println ("結果為:"+strResult);
22 
23             }else {
24                 System.out.println ("除數不能為零");
25             }
26 
27             scanner.close ();
28         } catch (Exception e) {
29             throw new RuntimeException("您輸入有誤:"+e.getMessage ());
30         }
31     }
32 }

 計算器(工廠)根據用戶需求,選擇(生成)符合需要的計算方式創建對應的實例對象,創建過程中需要需用戶參與。

 1 public class OperationFactory {
 2     public static Operation createOperate(String operate) {
 3         Operation oper = null;
 4         switch (operate){
 5             case "+":
 6                 oper = new OperationAdd ();
 7                 break;
 8             case "-":
 9                 oper = new OperationSub ();
10                 break;
11             case "*":
12                 oper = new OperationMul ();
13                 break;
14             case "/":
15                 oper = new OperationDiv ();
16                 break;
17         }
18         return oper;
19     }
20 }
 1 public class Operation{
 2     private double numberA = 0;
 3     private double numberB = 0;
 4 
 5     public double getNumberA() { return numberA; }
 6 
 7     public void setNumberA(double numberA) { this.numberA = numberA; }
 8 
 9     public double getNumberB() { return numberB; }
10 
11     public void setNumberB(double numberB) { this.numberB = numberB; }
12 
13     public double getResult(){ 
14         double result = 0;
15         return result;
16     }
17 }
18 
19 class OperationAdd extends Operation{
20     @Override
21     public double getResult() {
22         double result = 0;
23         result = getNumberA () + getNumberB ();
24         return result;
25     }
26 }
27 
28 class OperationSub extends Operation{
29     @Override
30     public double getResult() {
31         double result = 0;
32         result = getNumberA () - getNumberB ();
33         return result;
34     }
35 }
36 
37 class OperationMul extends Operation{
38     @Override
39     public double getResult() {
40         double result = 0;
41         result = getNumberA () * getNumberB ();
42         return result;
43     }
44 }
45 
46 class OperationDiv extends Operation{
47     @Override
48     public double getResult() {
49         double result = 0;
50         result = getNumberA () / getNumberB ();
51         return result;
52     }
53 }

 簡單工廠的缺點,不符合“開放封閉原則,要增加新的功能(計算方式)時,需要去修改工廠類(增加分支)。

2.2 多方法模式

是對普通工廠方法模式的改進,在普通工廠方法模式中,如果傳遞的字符串出錯,則不能正確創建對象,而多個工廠方法模式是提供多個工廠方法,分別創建對象。

 1 public class OperationFactory03 {
 2 
 3     public Operation add(){
 4         return new OperationAdd();
 5     }
 6 
 7     public Operation sub(){
 8         return new OperationSub ();
 9     }
10 
11     public Operation mul(){
12         return new OperationMul();
13     }
14 
15     public Operation div(){
16         return new OperationDiv();
17     }
18 }
 1 public class FactoryTest {
 2 
 3     public static void main(String[] args) {
 4 
 5         OperationFactory03 factory03 = new OperationFactory03();
 6         Operation add = factory03.add();
 7         
 8         add.setNumberA(20);
 9         add.setNumberB(10);
10         double result = add.getResult();
11         System.out.println(result);
12     }
13 }

2.3 靜態工廠方法模式

多個工廠方法模式里的方法置為靜態的,不需要創建實例,直接調用即可。

 1 public class OperationFactory {
 2 
 3     public static Operation add(){
 4         return new OperationAdd();
 5     }
 6 
 7     public static Operation sub(){
 8         return new OperationSub ();
 9     }
10 
11     public static Operation mul(){
12         return new OperationMul();
13     }
14 
15     public static Operation div(){
16         return new OperationDiv();
17     }
18 }
 1 //調用類
 2 public class FactoryTest {
 3 
 4     public static void main(String[] args) {
 5 
 6         Operation add = OperationFactory02.add();
 7         add.setNumberA(20);
 8         add.setNumberB(10);
 9         double result = add.getResult();
10         System.out.println(result);
11         
12     }
13 }

  總體來說,工廠模式適合:凡是出現了大量的產品需要創建,並且具有共同的接口時,可以通過工廠方法模式進行創建。在以上的三種模式中,第一種如果傳 入的字符串有誤,不能正確創建對象,第三種相對於第二種,不需要實例化工廠類,所以,大多數情況下,我們會選用第三種——靜態工廠方法模式。

3  抽象工廠模式

  工廠方法模式有一個問題就是,類的創建依賴工廠類,也就是說,如果想要拓展程序,必須對工廠類進行修改,這違背了閉包原則,所以,從設計角度考慮, 有一定的問題,如何解決?就用到抽象工廠模式,創建多個工廠類,這樣一旦需要增加新的功能,直接增加新的工廠類就可以了,不需要修改之前的代碼。因為抽象 工廠不太好理解,我們先看看圖,然后就和代碼,就比較容易理解。

接口類

1 public interface Sender {
2     public void Send();
3 }

兩個實現類

1 public class MsgSender implements Sender{
2 
3     @Override
4     public void Send() {
5         System.out.println("this is msgsender");
6     }
7 }
1 public class MailSender implements Sender {
2 
3     @Override
4     public void Send() {
5         System.out.println("this is mailsender!");
6     }
7 }

兩個工廠類

1 public class SendmsgFactory implements Provider {
2 
3     @Override
4     public Sender produce() {
5         return new MsgSender();
6     }
7 }
1 public class SendmailFactory implements Provider {
2 
3     @Override
4     public Sender produce() {
5         return new MailSender();
6     }
7 }

提供一個接口

1 public interface Provider {
2     public Sender produce();
3 }

測試類

1 public class FactoryTest {
2     public static void main(String[] args) {
3         Provider provider = new SendmailFactory();
4         Sender sender = provider.produce();
5         sender.Send();
6     }
7 }

  其實這個模式的好處就是,如果你現在想增加一個功能:發及時信息,則只需做一個實現類,實現Sender接口,同時做一個工廠類,實現Provider接口,就OK了,無需去改動現成的代碼。這樣做,拓展性較好,即依賴抽象不依賴具體原則的體現。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM