今天和大家分享一下設(shè)計(jì)模式中的 簡單工廠 工廠方法 抽象工廠

上圖是工廠模式百度百科的截圖,工廠模式(三種模式)的目的在于程序的可擴(kuò)展性,便于維護(hù),減少開發(fā)出錯(cuò),本人總結(jié)為工廠模式就是讓類的創(chuàng)建和使用分離,降低程序模塊之間的耦合程度(歡迎提出質(zhì)疑)
1.簡單工廠模式(Simple Factory Pattern)
我這里來拿《大話設(shè)計(jì)模式》中“大鳥”指導(dǎo)“小菜”完成的一個(gè)簡單工廠來舉例子(編寫一個(gè)簡單的計(jì)算器程序),這里我把他的c#代碼換成了本人學(xué)習(xí)的java -- ps:本人也是剛畢業(yè)不久的菜鳥一枚,正在看這本書就當(dāng)是寫個(gè)個(gè)人總結(jié)和大家分享一下。這本書評(píng)價(jià)不錯(cuò)京東有正版有能力的朋友可以支持一下作者。也可以看網(wǎng)絡(luò)上的pdf.....
首先來分析一下計(jì)算器程序的目的是為了得到一個(gè)計(jì)算結(jié)果,我們應(yīng)該抽象出這個(gè)結(jié)果首先我們是我們的抽象接口代碼
public interface Operation {
public double getResult(double number_a,double number_b);
}
Operation 接口中一個(gè)getResult 參數(shù)為 兩個(gè)double數(shù)。
假設(shè)目前只要滿足 + - * /的計(jì)算 好了我們來新建四個(gè)計(jì)算的運(yùn)算類分別實(shí)現(xiàn)接口Operation
public class OperationAdd implements Operation{
@Override
public double getResult(double number_a, double number_b) {
double result=0;
result= number_a+number_b;
return result;
}
}
public class OperationMul implements Operation{
@Override
public double getResult(double number_a,double number_b) {
double result=0;
result=number_a*number_b;
return result;
}
}
public class OperationSub implements Operation{
@Override
public double getResult(double number_a,double number_b) {
double result=0;
result= number_a-number_b;
return result;
}
}
public class OperationDiv implements Operation{
@Override
public double getResult(double number_a,double number_b) {
double result=0;
if(number_b==0)
{
try {
throw new Exception("除數(shù)不能為零");
} catch (Exception e) {
e.printStackTrace();
}
}
result=number_a/number_b;
return result;
}
}
這里大家是不是萬事具備只欠東風(fēng)了呢,問題來了具體的運(yùn)算類怎么調(diào)用 何時(shí)調(diào)用誰呢,這時(shí)間我們把我們的重點(diǎn)工廠類請出來了,讓它決定我們怎么使用具體的運(yùn)算類
public class OperationFactory {
private static OperationFactory instance ;
private OperationFactory(){}
public static OperationFactory getInstance(){
if (instance == null) {
synchronized (OperationFactory.class){
if (instance == null) {
instance = new OperationFactory();
}
}
}
return instance ;
}
public Operation createOperation(String operator){
Operation operation=null;
switch (operator)
{
case "+":
operation=new OperationAdd();
break;
case "-":
operation=new OperationSub();
break;
case "*":
operation=new OperationMul();
break;
case "/":
operation=new OperationDiv();
break;
default:
try {
throw new Exception("請輸入正確的運(yùn)算符");
} catch (Exception e) {
e.printStackTrace();
}
break;
}
return operation;
}
public Operation makeOperation(Class c)
{
Operation operation=null;
try {
operation=(Operation) Class.forName(c.getName()).newInstance();
}catch (InstantiationException e) {
System.out.println("不支持抽象類或接口");
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
System.out.println("沒有足夠權(quán)限,即不能訪問私有對(duì)象");
} catch (ClassNotFoundException e) {
System.out.println("類不存在");
e.printStackTrace();
} catch (ClassCastException e)
{
System.out.println("選擇的類不正確");
}
return operation;
}
}
我們先不管makeOperation方法先看createOperation方法。
createOperation只需要在調(diào)用的時(shí)間接受operator參數(shù)(+-*/)就能返回所對(duì)應(yīng)的運(yùn)算類了
下面是客戶端代碼
public class Main {
public static void main(String[] args) {
Operation operation;
operation=OperationFactory.getInstance().createOperation("+");
System.out.println(operation.getResult(1,1));
}
}
不用我說輸出結(jié)果為2
這里我們利用java的多態(tài)性調(diào)用了OperationAdd 類的getResult方法傳入了1 和1
但是怎么創(chuàng)建的OperationAdd 我們并沒有去管。這就是簡單工廠的一個(gè)實(shí)例了
也許大家會(huì)認(rèn)為這么設(shè)計(jì)出來的計(jì)算器程序應(yīng)該很完美了吧,然而并不是。
沒有遵守開放—封閉原則。所謂的“開放-封閉”原則就是開放接口,封閉修改。如果將來需要添加一個(gè)開方的算法,那么,在簡單工廠模式中,就必須在簡單工廠類中添加相應(yīng)的判斷語句。前面說的必須也不是那么絕對(duì),這時(shí)我們再看工廠類中的makeOperation 方法 如果要加入一個(gè)開方的運(yùn)算類,我們不改工廠類的邏輯是可以通過newInstance調(diào)用這個(gè)新的開方運(yùn)算律但是 newInstance是弱類型。所以想完全的按照開放—封閉原則我們還是要來看一下工廠方法模式
優(yōu)點(diǎn)
簡單工廠顧名思義就是你只管調(diào)用操作不需要管創(chuàng)建類的過程所以叫簡單工廠(根據(jù)客戶端的選擇條件動(dòng)態(tài)實(shí)例化相關(guān)的類,對(duì)客戶端調(diào)用來說除去了與具體產(chǎn)品的依賴)因?yàn)閯?chuàng)建的邏輯交給了工廠類,相當(dāng)于就是給類的創(chuàng)建做了封裝。
缺點(diǎn)
簡單工廠沒有遵守開放—封閉原則。所謂的“開放-封閉”原則就是開放接口,封閉修改。如果將來需要添加一個(gè)開方的算法,那么,在簡單工廠模式中,就必須在簡單工廠類中添加相應(yīng)的case語句!
2. 工廠方法模式
晚上更新
3. 抽象工廠模式
晚上更新