1. 程式人生 > >高階特性 三種工廠模式

高階特性 三種工廠模式

簡單工廠模式是屬於建立型模式,又叫做靜態工廠方法(Static Factory Method)模式,但不屬於23種GOF設計模式之一。簡單工廠模式是由一個工廠物件決定創建出哪一種產品類的例項。簡單工廠模式是工廠模式家族中最簡單實用的模式,可以理解為是不同工廠模式的一個特殊實現。

是通過專門定義一個類來負責建立其他類的例項,被建立的例項通常都具有共同的父類。 
我們從一個例項展開 
現在有一道面試題:使用java實現一個計算機控制檯程式,要求輸入數的運算,得到結果。 
這道題目最原始的寫法:

 


public class Computer {


public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.println("請輸入第一個數字");
float firstNum = in.nextFloat();
System.out.println("請輸入第二個數字");

float secondNum = in.nextFloat();
System.out.println("請輸入運算子");
String countQuato = in.next();
if("+".equals(countQuato)){
System.out.println("result:"+(firstNum+ secondNum) );

}else if("-".equals(countQuato));{
System.out.println("result:"+(firstNum- secondNum) );

}else if("*".equals(countQuato));{
System.out.println("result:"+(firstNum* secondNum) );

}else if("/".equals(countQuato));{
System.out.println("result:"+(firstNum/ secondNum) );


}
}

上面的寫法實現雖然簡單,但是卻沒有面向物件的特性,程式碼拓展性差,顯然不是出題者想要考察的意圖。 
那麼面向物件程式設計要如何在題中體現呢? 
在面向物件程式語言中,一切都是物件,所以上面運算子號也應當作物件來處理。 

public abstract class Operation {

public abstract float getResult(float firstNumber,float secondNumber);

}

我們首先建立一個抽象類

 

public class OperationFactory {

public static Operation getOperation(String quotaFlag){

Operation o = null;
switch (quotaFlag){
case "+": o =new AddOptation();
case "-": o =new SubOperationFactory();
case "*": o =new MulOperation();
case "/": o =new DivOperation();
default:break;

}
return o;
}


}


public class AddOPeration extends OPeration {

public float getResult(float firstNumber ,float secondNumber ){
return firstNumber+secondNumber;
}
}


public class SubOPeration extends OPeration {

public float getResult(float firstNumber ,float secondNumber ){
return firstNumber-secondNumber;
}
}

public class MulOPeration extends OPeration {

public float getResult(float firstNumber ,float secondNumber ){
return firstNumber*secondNumber;
}
}

public class DivOPeration extends OPeration {

public float getResult(float firstNumber ,float secondNumber ){
return firstNumber/secondNumber;
}
}

import java.util.Scanner;


public class Computer {


public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.println("請輸入第一個數字");
float firstNum = in.nextFloat();
System.out.println("請輸入第二個數字");

float secondNum = in.nextFloat();
System.out.println("請輸入運算子");
String countQuato = in.next();
if("+".equals(countQuato)){
System.out.println("result:"+(firstNum+ secondNum) );

}else if("-".equals(countQuato));{
System.out.println("result:"+(firstNum- secondNum) );

}else if("*".equals(countQuato));{
System.out.println("result:"+(firstNum* secondNum) );

}else if("/".equals(countQuato));{
System.out.println("result:"+(firstNum/ secondNum) );


}
}
private static float count(float firstNum,float secondNum,String countQuato){
//通過工廠類獲取物件
Operation Operation =OperationFactory.getOperation(countQuota);
return operation.getResult(firstNum,secondNum);

}





}

}

 

 

 

 

 

簡單工廠將物件的建立過程進行了封裝,使用者不需要知道具體的建立過程,只需要呼叫工廠類獲取物件即可。

這種簡單工廠的寫法是通過switch-case來判斷物件建立過程的。在實際使用過程中,違背了 開放-關閉原則,當然有些情況下可以通過反射呼叫來彌補這種不足。

 

 

 

簡單工廠的優點/缺點: 

  • 優點:簡單工廠模式能夠根據外界給定的資訊,決定究竟應該建立哪個具體類的物件。明確區分了各自的職責和權力,有利於整個軟體體系結構的優化。
  • 缺點:很明顯工廠類集中了所有例項的建立邏輯,容易違反GRASPR的高內聚的責任分配原則

 

 

2   工廠方法 定義一個用於建立物件的介面,讓子類決定例項化哪一個類,工廠方法使得一個類的例項化延遲到了子類 
工廠方法在簡單工廠的基礎上再包了一層工廠,所有的工廠都是此工廠的子類。而產生物件的型別由子類工廠決定。使用工廠方法來實現上面的加減乘除物件的建立

 

//定義上一級工廠店的介面
public interface IFractory {
public Operation generatOper();

}
//為每一個類建立工廠
/**
* 工廠方法 為每一個物件生成一個工廠類
*/
public class AddOperationFactory implements IFractory{
public Operation generatOper(){
return new AddOperation();
}
}public class SubOperationFactory implements IFractory{
public Operation generatOper(){
return new SubOperation();
}
}
public class MulOperationFactory implements IFractory{
public Operation generatOper(){
return new MulOperation();
}
}
public classDivOperationFactory implements IFractory{
public Operation generatOper(){
return new DivOperation();
}
}
//客戶端程式碼
IFractory fractory =new AddOperationFactory();
Operation Operation = fractory .generatOper();
Operation.getResult(firstNum,secondNum);

 

 

工廠方法將類的例項化推遲到了其子類。所以使用工廠方法模式時,需要客戶端決定例項化哪一個工廠類。選擇判斷問題還是存在的。也就是說,工廠方法把簡單的工廠內部邏輯判斷轉移到了客戶端來執行。你想要加的功能,本來是要改工廠類的,而現在是修改客戶端。不過,我們在某些情況下通過工廠方法,只需要修改一行例項化的程式碼就可以實現系統元素的切換(比如切換資料來源)。這也是很方便的。

工廠方法模式Factory Method,又稱  多型性工廠模式。在工廠方法模式中,核心的工廠類不再負責所有的產品的建立,而是將具體建立的工作交給子類去做。該核心類成為一個抽象工廠角色,僅負責給出具體工廠子類必須實現的介面,而不接觸哪一個產品類應當被例項化這種細節。

2.定義: 

工廠方法模式是簡單工廠模式的衍生,解決了許多簡單工廠模式的問題。首先完全實現‘開-閉 原則’,實現了可擴充套件。其次更復雜的層次結構,可以應用於產品結果複雜的場合。

3.延伸: 

在上面簡單工廠的引入中,我們將例項化具體物件的工作全部交給了專門負責建立物件的工廠類(場務)中,這樣就可以在我們得到導演的命令後建立對應的車(產品)類了。但是劇組的導演是性情比較古怪的,可能指令也是無限變化的。這樣就有了新的問題,一旦導演發出的指令時我們沒有預料到的,就必須得修改原始碼。這也不是很合理的。工廠方法就是為了解決這類問題的。

 

工廠方法的優點/缺點: 

  • 優點:
    • 子類提供掛鉤。基類為工廠方法提供預設實現,子類可以重寫新的實現,也可以繼承父類的實現。-- 加一層 間接性,增加了靈活性
    • 遮蔽產品類。產品類的實現如何變化,呼叫者都不需要關心,只需關心產品的介面,只要介面保持不變,系統中的上層模組就不會發生變化。
    • 典型的解耦框架。高層模組只需要知道產品的抽象類,其他的實現類都不需要關心,符合迪米特法則,符合依賴倒置原則,符合里氏替換原則。
    • 多型性:客戶程式碼可以做到與特定應用無關,適用於任何實體類。
  • 缺點:需要Creator和相應的子類作為factory method的載體,如果應用模型確實需要creator和子類存在,則很好;否則的話,需要增加一個類層次。(不過說這個缺點好像有點吹毛求疵了)

抽象工廠:

提供一個建立一系列相關相互依賴物件的介面,而無需指定他們具體的類。抽象工廠為不同產品族的物件建立提供介面。 
使用場景:系統需要在不同產品族進行切換 
程式碼實現:

 

import MulOperationFactory.IDepartment;

//不同產品組使用一個工廠
public class SalServerFactory implements IFacfory {
public IUser createUser(){
return new SqIServerUser();
}

}public IDepartment createDepartment(){

return new SqIServerDepartment();


}
public class AccessFactory implements IFacfory{
public IUser createUser(){
return new AccessUser();
public IDepartment createDepartment(){

return new AccessDepartment();

}

客戶端:
IFacfory facfory = new AccessFactory();
IUser user = facfory. createUser();
IDepartment department = facfory. createDepartment();
user.insert();
user.getById();
department.insert();
department.getDepartmentById();

 

 

 

 

 

 

 

第一個抽象工廠最大的好處就是便於交換產品系列,具體工廠在程式碼中一般只出現一次。這就使得改變應用的具體工廠很容易。 

第二個好處是他能讓具體的建立物件例項和客戶端分離,客戶端是通過他們的抽象介面操作例項 

抽象工廠不太易於拓展,如果需要自增功能,或者自增產品,則需要至少修改三個類,而且例項化的程式碼是寫死在程式中的 , 這樣無法避免違背開放-關閉原則。 
對於上述問題,可以通過配置檔案,結合反射的方式來解決。

  1. 3.   抽象工廠模式是所有形態的工廠模式中最為抽象和最具一般性的一種形態。抽象工廠模式是指當有多個抽象角色時,使用的一種工廠模式。抽象工廠模式可以向客戶端提供一個介面,使客戶端在不必指定產品的具體的情況下,建立多個產品族中的產品物件。根據里氏替換原則,任何接受父型別的地方,都應當能夠接受子型別。因此,實際上系統所需要的,僅僅是型別與這些抽象產品角色相同的一些例項,而不是這些抽象產品的例項。換言之,也就是這些抽象產品的具體子類的例項。工廠類負責建立抽象產品的具體子類的例項。

 

抽象工廠:定義

為建立一組相關或相互依賴的物件提供一個介面,而且無需指定他們的具體類。

抽象工廠的優點/缺點: 

  • 優點:
    • 抽象工廠模式隔離了具體類的生產,使得客戶並不需要知道什麼被建立。
    • 當一個產品族中的多個物件被設計成一起工作時,它能保證客戶端始終只使用同一個產品族中的物件。
    • 增加新的具體工廠和產品族很方便,無須修改已有系統,符合“開閉原則”。
  • 缺點:增加新的產品等級結構很複雜,需要修改抽象工廠和所有的具體工廠類,對“開閉原則”的支援呈現傾斜性。(不過說這個缺點好像有點吹毛求疵了)