Java設計模式很難嗎,這篇帶你熟悉設計模式
3。1 概述
可以發現,設計模式好像都是類似的。越看越感覺都著不多。其實都是類似面向介面程式設計的一種體現,只不過側重點不一樣或者說要體現的結果不一樣。
3。2 使用場景
問題一:應對可能變化的物件實現
方案:間接建立
模式:工廠模式
問題二:為請求指定相應的操作(類似請假審批,不同時長對應不同職位的審批人)
方案:程式根據請求動態選擇操作
模式:責任鏈模式
3。3 具體說明
3。3。1 策略模式
策略模式說明
一個行為型模式,包含多個行為或職責的業務,透過策略模式簡化
public class StrategyContext { Strategy strategy; public StrategyContext(Strategy strategy) { this。strategy = strategy; } /** * */ public int context(int a, int b) { return strategy。operator(a,b); }}
策略模式的核心為StrategyContext上下文類,持有strategy物件,在context完成操作。
策略模式實踐
如何使用策略模式解決大量使用if else 或大量switch問題,策略模式+反射。
策略模式後好像使用都還是要用if else來決定呼叫哪個類,所以在引入策略模式後,在上下文類還要增加反射。
public class StrategyContext { Strategy strategy; public StrategyContext(String type) throws Exception { Class clazz = Class。forName(type); this。strategy = (Strategy) clazz。newInstance(); } /** * */ public int context(int a, int b) { return strategy。operator(a,b); }
當然這裡的type可以用個列舉來解決。感覺代價非常大是不是沒必要,不過程式碼的可讀性還是增強了。
p。s。 在框架裡策略模式中的Context一般不會直接出現,類似spring中直接在使用時就透過註解給設定了
3。3。2、裝飾器模式
描述:原介面Shape不變,方法數量不變,在
方法實現中
增加修飾
場景:
場景一:一個類功能簡單,滿足不了我們的需求
場景二:給原方法增加日誌功能,不改變原方法,新的實現類去實現此功能,帶入的物件為介面物件
特點
原介面Shape不動,增加新的裝飾類ShapeDecorator
原方法名不變,只是增加或修飾此方法體
ColorShapeDecorator裝飾類持有原物件,只是增加了修飾
public class ColorShapeDecorator extends ShapeDecorator { public ColorShapeDecorator(Shape shape) { super(shape); } @Override public void draw() { setColor(); shape。draw(); } private void setColor() { //設定畫圖顏色 }}
3。3。3 代理模式
設定一箇中間代理來控制訪問原目標物件,達到
增強
原物件的功能和
簡化
訪問方式的目的
場景:
場景一:不改變原方法,對原方法增加耗時的計算
場景二:rpc遠端呼叫,client端進行動態代理類似耗時計算一樣,使用者不用關心client的具體實現
分類
靜態代理模式
動態代理模式
說明
靜態代理模式
/** * 與介面卡模式的區別,介面卡模式主要改變所考慮物件的介面, * 而代理模式不能改變所代理類的介面。與裝飾器模式的區別, * 裝飾器模式是為了增強功能,代理模式是為了加以控制 */public class ProxySigntureService implements SigntureService { private SigntureService signatureService; /** * Default constructor */ public ProxySigntureService(SigntureService signatureService) { this。signatureService = signatureService; } public void sign() { //控制對這個物件的訪問 // 實現電子簽名 }}
動態代理模式
public class DynamicProxySignatureService implements InvocationHandler { private Object obj; public DynamicProxySignatureService(Object obj) { this。obj = obj; } @Override public Object invoke(Object proxyObj, Method method, Object[] objects) throws Throwable { return method。invoke(obj,objects); }}
參考文章:https://blog。csdn。net/liujiahan629629/article/details/19428485
3。3。4 介面卡模式
描述:
原介面不變,增加
方法數量
場景:
場景一:原介面不變,在基礎上增加新的方法。
場景二:介面的抽象方法很多,不想一一實現,使用介面卡模式繼承原實現類,再實現此介面
介面卡模式適合需要
增加一個新介面的需求
,在原介面與實現類基礎上需要增加新的介面及方法。類似原介面只能method01方法,需求是增加method02方法,同時不再使用之前介面類。
新介面
public interface Targetable { /** * */ public void method01(); /** * */ public void method02();}
原介面實現類
public class Source { public void method01() { // TODO implement here }}
介面卡類,用於實現新介面。繼承原實現類,同時實現新介面。
public class Adapter extends Source implements Targetable { /** * */ public void method02() { // TODO implement here }}
測試類
public class AdapterTest { public static void main(String[] args) { Targetable targetable = new Adapter(); targetable。method01(); targetable。method02(); }}
3。3。5 單例模式
保證被建立一次,節省系統開銷。
1)單例實現方式
餓漢式
懶漢式
懶漢式+synchronized
雙重校驗
靜態內部類
列舉(推薦方式)
2)實現程式碼
餓漢式
package com。hanko。designpattern。singleton;/** * 餓漢式 (餓怕了,擔心沒有吃,所以在使用之前就new出來) *優點:實現簡單,安全可靠 *缺點:在不需要時,就已例項化了 * @author hanko * @version 1。0 * @date 2020/9/14 18:50 */public class HungrySingleton { //特點一 靜態私有變數 直接初始化 private static HungrySingleton instance = new HungrySingleton(); //特點二 建構函式私有 private HungrySingleton(){ } public static HungrySingleton getInstance(){ return instance; } public void doSomething(){ //具體需要實現的功能 }}
懶漢式
package com。hanko。designpattern。singleton;/** * 懶漢式(非常懶,所以在要使用時再去new) *優點:簡單 *缺點:存線上程安全問題 * @author hanko * @version 1。0 * @date 2020/9/14 18:50 */public class SluggardSingleton { //特點一 靜態私有變數,先不初始化 private static SluggardSingleton instance; //特點二 建構函式私有 private SluggardSingleton(){ } //特點三 null判斷,沒有例項化就new public static SluggardSingleton getInstance(){ if(instance == null){ instance = new SluggardSingleton(); } return instance; } public void doSomething(){ //具體需要實現的功能 }}
懶漢式+Synchronized
package com。hanko。designpattern。singleton;/** * 懶漢式(非常懶,所以在要使用時再去new) *優點:簡單 *缺點:存線上程安全問題 * @author hanko * @version 1。0 * @date 2020/9/14 18:50 */public class SluggardSingleton { //特點一 靜態私有變數,先不初始化 private static SluggardSingleton instance; //特點二 建構函式私有 private SluggardSingleton(){ } //特點三 null判斷,沒有例項化就new public static synchronized SluggardSingleton getInstance(){ if(instance == null){ instance = new SluggardSingleton(); } return instance; } public void doSomething(){ //具體需要實現的功能 }}
雙重校驗
package com。hanko。designpattern。singleton;/** * 雙重校驗 *對懶漢式單例模式做了執行緒安全處理增加鎖機制 * volatile變數級 * synchronized 類級 * @author hanko * @version 1。0 * @date 2020/9/15 9:53 */public class DoubleCheckSingleton { //特點一 靜態私有變數,增加volatile變數級鎖 private static volatile DoubleCheckSingleton instance; //特點二 建構函式私有 private DoubleCheckSingleton(){ } //特點三 雙重null判斷 synchronized類級鎖 public static DoubleCheckSingleton getInstance(){ if (instance == null){ synchronized(DoubleCheckSingleton。class){ if (instance == null){ instance = new DoubleCheckSingleton(); } } } return instance; }}
靜態內部類
package com。hanko。designpattern。singleton;/** * 內部靜態類方式 *優點:靜態內部類不會在InnerStaticSingleton類載入時載入, * 而在呼叫getInstance()方法時才載入 *缺點:存在反射攻擊或者反序列化攻擊 * @author hanko * @version 1。0 * @date 2020/9/15 10:03 */public class InnerStaticSingleton { //特點一:建構函式私有 private InnerStaticSingleton(){ } //特點二:靜態內部類 private static class InnerSingleton{ private static InnerSingleton instance = new InnerSingleton(); } public InnerSingleton getInstance(){ return InnerSingleton。instance; } public void doSomething(){ //do Something }}
列舉(推薦方式)
package com。hanko。designpattern。singleton;/** * 列舉實現單例簡單安全 * * @author hanko * @version 1。0 * @date 2020/9/14 19:01 */public enum EnumSingleton { INS; private Singleton singleton; EnumSingleton() { singleton = new Singleton(); } public void doSomething(){ singleton。。。 //具體需要實現的功能 }}EnumSingleton。INS。doSomething();
3。3。6 工廠模式
(簡單工廠、抽象工廠):解耦程式碼。
簡單工廠:用來生產同一等級結構中的任意產品,對於增加新的產品,無能為力。
工廠方法:用來生產同一等級結構中的固定產品,支援增加任意產品。
抽象工廠:用來生產不同產品族的全部產品,對於增加新的產品,無能為力;支援增加產品族。
參考文章:https://zhuanlan。zhihu。com/p/248497545
3。3。7 觀察者模式
定義了物件之間的一對多的依賴,這樣一來,當一個物件改變時,它的所有的依賴者都會收到通知並自動更新。
3。3。8 外觀模式
提供一個統一的介面,用來訪問子系統中的一群介面,外觀定義了一個高層的介面,讓子系統更容易使用。
3。3。9 狀態模式
允許物件在內部狀態改變時改變它的行為,物件看起來好像修改了它的類。與策略模式類似,策略模式側重點在一個事的不同實現方式抽離出來,而狀態模式是一個事的不同狀態抽離出來(開始、進行中、結束),每次狀態完成自己的業務邏輯。
3。4 總結:
介面卡模式(原功能不變,增加新功能)、裝飾器模式(裝飾原功能)、代理模式(控制原功能)
策略模式側重點在一個事的不同實現方式抽離出來,而狀態模式是一個事的不同狀態抽離出來(開始、進行中、結束),每次狀態完成自己的業務邏輯。