本文咱們說一下建立型設計模式中的工廠模式,可細分爲三種:分別是簡單工廠模式,工廠方法模式,抽象工廠模式設計模式
下面一一講解:ide
一.簡單工廠模式測試
簡單工廠模式屬於類的建立型模式,又叫靜態工廠方法模式。經過專門定義一個工廠類來負責建立其餘類的實例,被建立的實例一般都具備共同的父類。優化
簡單工廠模式包含三種角色:this
1.工廠角色(Creator)spa
這是簡單工廠模式的核心,它用來負責實現建立全部實例的內部邏輯。工廠類能夠被外界直接調用,建立所需的產品對象。設計
2.抽象角色(Product)code
這是簡單工廠模式所建立的全部對象的父類,它負責描述全部實例所共有的公共接口。該類能夠是接口,也能夠是抽象類。對象
3.具體產品角色(Concrete Product)blog
簡單工廠模式所建立的具體的實例對象。
以上面的UML爲例,表示的是一個用簡單工廠方法模式實現的計算器程序。
其中Operator是一個抽象類,其中包含屬性numberA及numberB,還有一個方法getResult()用於返回計算的結果,它的角色是抽象角色(Product)。
下面的AddOperator,SubOperator,MulOperator,DivOperator是Operator的子類,分別表明加減乘除四種運算,他們的角色是具體產品角色(Concrete Product)。
OperatorFactory是工廠類,其中的createOperator()方法用於建立計算器對象。
下面看代碼:
1 /** 2 * 計算器抽象類 3 * Created by lixiuyu 4 */ 5 public abstract class Operator { 6 7 private double numberA = 0.0; 8 private double numberB = 0.0; 9 10 protected abstract double getResult() throws Exception; 11 12 public double getNumberA() { 13 return numberA; 14 } 15 16 public void setNumberA(double numberA) { 17 this.numberA = numberA; 18 } 19 20 public double getNumberB() { 21 return numberB; 22 } 23 24 public void setNumberB(double numberB) { 25 this.numberB = numberB; 26 } 27 }
1 /** 2 * 加法類 3 * Created by lixiuyu 4 */ 5 public class AddOperator extends Operator { 6 7 protected double getResult() { 8 return getNumberA() + getNumberB(); 9 } 10 }
/** * 減法類 * Created by lixiuyu. */ public class SubOperation extends Operator { @Override protected double getResult() { return getNumberA() - getNumberB(); } }
/** * 乘法類 * Created by lixiuyu. */ public class MulOperation extends Operator { @Override protected double getResult() { return getNumberA() * getNumberB(); } }
1 /** 2 * 除法類 3 * Created by lixiuyu. 4 */ 5 public class DivOperation extends Operator { 6 @Override 7 protected double getResult() throws Exception { 8 if(getNumberB() == 0.0){ 9 throw new Exception("除數不能爲0"); 10 }else{ 11 return getNumberA() / getNumberB(); 12 } 13 } 14 }
1 /** 2 * 工廠類 3 * Created by lixiuyu. 4 */ 5 public class OperatorFactory { 6 public static Operator createOperator(String operation){ 7 Operator operator = null; 8 switch (operation){ 9 case "+": 10 operator = new AddOperator(); 11 break; 12 case "-": 13 operator = new SubOperator(); 14 break; 15 case "*": 16 operator = new MulOperator(); 17 break; 18 case "/": 19 operator = new DivOperator(); 20 break; 21 } 22 return operator; 23 } 24 }
測試類:
1 /** 2 * Created by lixiuyu. 3 */ 4 public class OperatorTest { 5 public static void main(String[] args) { 6 Operator operator = OperatorFactory.createOperator("+"); 7 operator.setNumberA(10); 8 operator.setNumberB(5); 9 try { 10 System.out.println(operator.getResult()); 11 } catch (Exception e) { 12 e.printStackTrace(); 13 } 14 } 15 }
最後輸出15
這樣寫的計算器是否是比if()...else()...寫出來的好呢?
下面咱們分析一下簡單工廠模式的優缺點:
在簡單工廠模式中,工廠類是整個模式的關鍵所在。它包含了必要的判斷邏輯,可以根據外界給定的條件去判斷應該建立哪一個具體類的實例。用戶在使用時能夠直接根據工廠類去建立所需的實例,而無需關係這些對象是如何組織並建立的,從這一點上來講,這有利於整個軟件體系結構的優化。
可是,簡單工廠模式的缺點也正體如今工廠類上,因爲工廠類中集中了全部實例的建立邏輯,當咱們增長了一個新的具體類時,須要同時修改工廠類(多加一個if),這違反了「開閉原則」。
二.工廠方法模式
工廠方法模式是對普通工廠方法模式的改進,在普通工廠方法模式中,若是傳遞的字符串出錯,則不能正確建立對象,而工廠方法模式是提供多個工廠方法,分別建立對象。
依舊以上面的計算器爲例,進行講解:
咱們對OperatorFactory類更改以下:
1 /** 2 * Created by lixiuyu. 3 */ 4 public class OperatorFactory { 5 6 public static Operator createAddOperator(){ 7 return new AddOperator(); 8 } 9 10 public static Operator createSubOperator(){ 11 return new SubOperator(); 12 } 13 14 public static Operator createMulOperator(){ 15 return new MulOperator(); 16 } 17 18 public static Operator createDivOperator(){ 19 return new DivOperator(); 20 } 21 }
此時將不會出現簡單工廠模式由於字符串傳錯而不能正常建立對象的問題。
1 /** 2 * Created by lixiuyu. 3 */ 4 public class OperatorTest { 5 public static void main(String[] args) { 6 Operator operator = OperatorFactory.createAddOperator(); 7 operator.setNumberA(10); 8 operator.setNumberB(5); 9 try { 10 System.out.println(operator.getResult()); 11 } catch (Exception e) { 12 e.printStackTrace(); 13 } 14 } 15 }
執行結果:15.0
總結:
與簡單工廠模式相比,工廠方法模式避免了由於傳入字符串錯誤致使沒法正常建立對象的問題,但須要添加新的具體類時,仍然須要修改工廠類,這仍然違背「開閉原則」。
三.抽象工廠模式
工廠方法模式有一個問題就是,類的建立依賴工廠類,也就是說,若是想要拓展程序,必須對工廠類進行修改,這違背了開閉原則,因此,從設計角度考慮,有必定的問題,如何解決?就用到抽象工廠模式。抽象工廠模式就是將對象工廠的建立抽象到一個接口中。抽象工廠類不在負責產品的建立,僅僅負責定義具體工廠子類必須實現的接口,這樣進一步抽象化的好處是使得能夠再不修改具體工廠角色的狀況下引進新的產品。
這樣一旦須要增長新的功能,直接增長新的工廠類就能夠了,不須要修改以前的代碼,符合開閉原則。
抽象工廠模式中包含的角色及職責:
1.抽象工廠角色(Creator)
這是抽象工廠模式的核心,任何工廠類必須實現這個接口。
2.具體工廠角色(Concrete Creator)
它是抽象工廠的一個實現,負責實例化產品對象。
3.抽象角色(Product)
抽象工廠模式所建立的全部對象的父類,它負責描述全部實例所共有的公共接口。
3.具體產品角色(Concrete Product)
抽象工廠模式所建立的具體的實例對象。
下面結合UML圖理解一下:
在抽象工廠中定義了各個實現類須要實現的接口createOperator(),各個實現類按照各自的規則實例化Operator對象。代碼以下:
1 /** 2 * Created by lixiuyu. 3 */ 4 public interface OperatorFactory { 5 public Operator createOperator(); 6 }
接下來定義OperatorFactory的具體實現類,即具體工廠類。
1 /** 2 * Created by lixiuyu. 3 */ 4 public class AddOperatorFactory implements OperatorFactory { 5 6 @Override 7 public Operator createOperator() { 8 return new AddOperator(); 9 } 10 }
1 /** 2 * Created by lixiuyu. 3 */ 4 public class SubOperatorFactory implements OperatorFactory { 5 @Override 6 public Operator createOperator() { 7 return new SubOperator(); 8 } 9 }
1 /** 2 * Created by lixiuyu. 3 */ 4 public class MulOperatorFactory implements OperatorFactory { 5 @Override 6 public Operator createOperator() { 7 return new MulOperator(); 8 } 9 }
1 /** 2 * Created by lixiuyu. 3 */ 4 public class DivOperatorFactory implements OperatorFactory { 5 @Override 6 public Operator createOperator() { 7 return new DivOperator(); 8 } 9 }
下面是測試類:
1 /** 2 * Created by lixiuyu. 3 */ 4 public class OperatorFactoryTest { 5 6 public static void main(String[] args) { 7 OperatorFactory factory = new AddOperatorFactory(); 8 Operator operator = factory.createOperator(); 9 operator.setNumberA(10.0); 10 operator.setNumberB(5.0); 11 try { 12 System.out.println(operator.getResult()); 13 } catch (Exception e) { 14 e.printStackTrace(); 15 } 16 } 17 }
運行結果:15.0
因而可知,當咱們須要增長一種運算時,只須要增長一個具體運算及具體工廠類,原有的具體工廠類不須要作任何改動,即作到了"對擴展開放,對修改關閉",很好的符合了開閉原則。