設計模式詳解——單例、工廠、抽象工廠
阿新 • • 發佈:2021-10-15
tags: [#設計模式]
從今天開始,我們逐一看下常用的設計模式,希望能夠儘可能搞清楚它們的應用場景,以便我們能夠寫出更優秀的程式碼。
1、單例模式
核心要點
- 構造方法私有
- 構造由
static
修飾的、返回例項的方法
優勢
- 減少建立
Java
例項所帶來的系統開銷 - 便於系統跟蹤單個Java例項的宣告週期、例項狀態等
示例程式碼
package singleton; public class Singleton { private static Singleton instance; private Singleton() {} public static Singleton getInstance() { if(instance == null) { instance = new Singleton(); } return instance; } }
場景
執行緒池(threadpool
)、快取(cache
)、日誌物件
2、簡單工廠模式
要點
- 通過工廠類的形式進行解耦合
- 依賴關係通過介面解耦合
優缺點
- 讓物件的呼叫者和物件建立過程分離,當物件呼叫者需要物件時,直接向工廠請求即可;
- 避免了物件的呼叫者和物件的實現類以硬解碼方式耦合,提高了系統的可維護性、拓展性;
- 需要注意的一個陷阱是:當產品修改時,工廠類也要做相應的修改;
示例程式碼
這裡的computer
依賴了Printer
類,但是如果直接寫Printer
的話,會直接影響當前類的擴充套件,比如我們後期增加了Writer
,Writer
和Printer
只是方法不一致,這時候如果用簡單工廠模式,就可以完美解決這個問題。
當然,這時依然需要修改OutputFactory
的程式碼,但是對Computer
是不需要修改的。
public class Computer {
private Output out;
public Computer(Output out) {
this.out = out;
}
public void keyIn(String msg) {
out.getData(msg);
}
public void print() {
out.out();
}
}
簡單工廠
package simplefactory; public class OutputFactory { public Output getOutput() { return new Printer(); } }
介面
package simplefactory;
public interface Output {
final int MAX_CACHE_LINE=200;
void getData(String msg);
void out();
}
介面實現類
package simplefactory;
public class Printer implements Output {
private String[] printData = new String[MAX_CACHE_LINE];
private int dataNum = 0;
@Override
public void getData(String msg) {
if(dataNum >= MAX_CACHE_LINE) {
System.out.println("輸出佇列已滿,新增失敗");
} else {
printData[dataNum++] = msg;
}
}
@Override
public void out() {
while(dataNum > 0) {
System.out.println("印表機列印:" + printData[0]);
System.arraycopy(printData, 1, printData, 0, --dataNum);
}
}
}
測試類
package simplefactory;
public class Test {
public static void main(String[] args) {
OutputFactory of = new OutputFactory();
Computer c = new Computer(of.getOutput());
c.keyIn("hello world");
c.keyIn("java");
c.keyIn("spring");
c.print();
}
}
3、工廠方法和抽象工廠
要點
- 和簡單工廠相比,工廠方法多了一個介面,也就是工廠介面,
Ouput
子類的工廠類均繼承該介面,實現getOutput()
方法 - 當使用工廠方法設計模式時,物件呼叫者需要與具體的工廠類進行耦合:當需要不同物件時,程式需要呼叫相應工廠物件的方法來得到所需的物件
- 對於採用工廠方法的設計架構,客戶端程式碼成功與被呼叫物件實現了分離,但帶來了另一種耦合:客戶端程式碼與不同的工廠類耦合
- 為了解決上面的耦合,增加一個工廠類,用於建立不同的工廠物件,這個特殊的工廠類被稱為抽象工廠類,這種設計模式被稱為抽象工廠模式
比較
和簡單工廠相比,抽象工廠降低了目標例項與例項工廠的耦合性,但是它又引入了抽象工廠的耦合關係。
在簡單工廠模式中,要建立一個物件的例項,直接呼叫該物件的工廠方法即可,當然前提條件是增加該物件時要同步增加它的工廠方法;
在抽象工廠模式中,不僅對例項物件做了抽象處理,還對物件的工廠做了抽象處理,所以在例項化一個物件的時候,要先例項化它的工廠,然後再通過工廠方法例項化物件(實線表示程式碼實際執行流程,虛線表示解耦過程,工廠的工廠創建出來的是抽象工廠的例項,抽象工廠最終建立的是物件的抽象介面)
示例程式碼
例項工廠介面:
// 工廠介面
package abstractfactory;
import simplefactory.Output;
/**
*
*TODO output工廠介面
*
* @author CaoLei 2018年7月1日下午3:19:36
* OutputFactory
*/
public interface OutputFactory {
Output getOutput();
}
例項工廠實現:
// 工廠方法,工廠類
package abstractfactory;
import simplefactory.BetterPrinter;
import simplefactory.Output;
public class BetterPrinterFactory implements OutputFactory {
@Override
public Output getOutput() {
return new BetterPrinter();
}
}
例項工廠例項化方法:
// 抽象工廠,抽象工廠類
package abstractfactory;
public class OutputFactoryFactory {
public static OutputFactory getOutputFactory(String type) {
if ("better".equals(type)) {
return new BetterPrinterFactory();
} else {
return new PrinterFactory();
}
}
}
好了,今天就先說這三種設計模式,明天我們來繼續看其他的設計模式。