1. 程式人生 > 其它 >設計模式詳解——命令、代理、策略模式

設計模式詳解——命令、代理、策略模式

tags: [#設計模式,,#策略模式,#命令模式,#代理模式]

前言

今天我們主要來看三種設計模式,他們分別是命令模式、代理模式和策略模式。廢話少說,下面我們直接開始吧!

設計模式

命令模式

命令模式簡單來說,就是將一組操作整合成一個通用的命令,然後通過一個通用的執行器來執行的一種設計模式,這種設計模式也是為了更好地實現程式碼地解耦。

這種設計模式就類似於一個遙控器,遙控器上的每一個按鈕都對應一個命令,我們不需要關心命令內部執行流程,只需要按下(執行)這個按鈕,然後相關命令就會被執行。

這麼說還是有點抽象,下面我們通過一個簡單的示例來演示下命令模式的用法。

程式碼都很簡單,對於程式碼這裡就不詳細說明了,各位小夥伴要關注的是程式碼的設計,以及他所達到的解耦效果。

要執行命令的物件
public class Light {
    public void on() {
        System.out.println("開燈了");
    }

    public void off() {
        System.out.println("關燈了");
    }
}
命令介面
public interface Command {
    void execute();
}
命令實現

關燈命令

public class LightOffCommand implements Command {
    Light light;

    public LightOffCommand(Light light) {
        this.light = light;
    }
    @Override
    public void execute() {
        light.off();
    }
}

開燈命令

public class LightOnCommand implements Command {
    Light light;

    public LightOnCommand(Light light) {
        this.light = light;
    }

    @Override
    public void execute() {
        light.on();
    }
}
命令執行(控制層)
public class SimpleRemoteControl {
    Command command;

    public SimpleRemoteControl() {
    }

    public void setCommand(Command command) {
        this.command = command;
    }

    public void buttonWasPressed() {
        command.execute();
    }
}
測試程式碼
public class CommandTest {
    @Test
    public void testCommand() {
        // 建立控制器例項
        SimpleRemoteControl control = new SimpleRemoteControl();
        // 建立命令執行物件例項
        Light light = new Light();
        // 建立命令例項
        LightOnCommand onCommand = new LightOnCommand(light);
        LightOffCommand offCommand = new LightOffCommand(light);
        // 開燈
        // 設定命令
        control.setCommand(onCommand);
        // 執行命令
        control.buttonWasPressed();
        // 關燈操作
        control.setCommand(offCommand);
        control.buttonWasPressed();
    }
}
執行結果

如果各位小夥伴如果用過struts框架的話,應該對這個設計模式不陌生,因為在struts的業務控制層中,命令模式被廣泛應用。

優點

關於命令模式的好處,想必各位小夥伴都已經看出來了:它實現了控制層與具體物件之間的耦合關係,當我們具體的業務物件發生變化時,我們只需要調整其所對應的命令實現類即可,而不需要調整控制層相關程式碼,即提高了系統的可擴充套件性,又保證了它的健壯性,是不是美滋滋呢!

要點
  • 命令模式將發出請求的物件和執行請求的物件解耦
  • 在被解耦的兩者之間是通過命令物件進行溝通的。命令物件封裝了接收者和一個或一組動作
  • 呼叫者通過呼叫命令物件的execute()(方法名可以自己起)發出請求,這回使得接受者的動作被呼叫
  • 呼叫者可以接受命令當做引數,甚至在執行時動態地進行
  • 命令可以支援撤銷,做法是實現一個undo()方法(也可以自定義)來回到execute()被執行前的狀態
  • 巨集命令是命令的一種簡單延伸,允許呼叫多個命令,巨集方法也可以支援撤銷。
  • 實際操作時,很常見使用“聰明”命令物件,也就是直接實現了請求,而不是將工作委託給接收者
  • 命令也可以用來實現日誌和事務系統

代理模式

我發現關於代理模式的內容還是比較多的,考慮到篇幅和時間,我們今天先說下它的要點,同時由於之前我在分享手寫rpc框架內容的時候已經展示過動態代理的相關用法了,所以今天暫時先不展開講,等後面把這塊內容徹底梳理清楚之後,我們再來繼續分享。

關於手寫rpc框架中動態代理的內容,可以移步到這裡看下:

要點
  • 代理模式為另一個物件提供代表,以便控制客戶對物件的訪問,管理訪問的方式有許多種
  • 遠端代理管理客戶和遠端物件之間的互動
  • 虛擬代理控制訪問例項化開銷大的物件
  • 保護代理基於呼叫者控制物件方法的訪問
  • 代理模式有許多變體,例如:快取代理、同步代理、防火牆代理和寫入時複製代理
  • 代理在結構上類似裝飾者,但是目的不同。裝飾是模式為物件加上行為,而代理則是控制訪問
  • java內建的代理支援,可以根據需要建立動態代理,並將所有呼叫分配到所選的處理器
  • 和其他的包裝者一樣,代理會造成你的設計中類的數目增加。

策略模式

關於策略模式,我們前幾天剛分享了一篇與之相關的應用內容,各位小夥伴可以回顧下:

策略模式主要是為了優化程式碼中的邏輯問題,特別是在有多種演算法相似的情況下,使用 if...else 所帶來的複雜和難以維護的問題。

策略這個詞,我們在日常生活中也會經常用到,意思也基本上一致,這裡的策略模式就是我們做事策略思維在軟體開發中的應用。

應用例項
  • 諸葛亮的錦囊妙計,每一個錦囊就是一個策略。
  • 旅行的出遊方式,選擇騎自行車、坐汽車,每一種旅行方式都是一個策略。
  • JAVA AWT 中的 LayoutManager
使用場景
  • 如果在一個系統裡面有許多類,它們之間的區別僅在於它們的行為,那麼使用策略模式可以動態地讓一個物件在許多行為中選擇一種行為。

  • 一個系統需要動態地在幾種演算法中選擇一種。

  • 如果一個物件有很多的行為,如果不用恰當的模式,這些行為就只好使用多重的條件選擇語句來實現。

例項程式碼

下面是數字加減的策略模式實現,各位小夥伴可以試著從程式碼中理解下策略模式。

策略介面

public interface Strategy {
   int doOperation(int num1, int num2);
}

加法策略實現

public class OperationAdd implements Strategy{
   @Override
   public int doOperation(int num1, int num2) {
      return num1 + num2;
   }
}

減法策略實現

public class OperationSubtract implements Strategy{
   @Override
   public int doOperation(int num1, int num2) {
      return num1 - num2;
   }
}

策略控制器

public class StrategyControl {
   private Strategy strategy;
 
   public StrategyControl(Strategy strategy){
      this.strategy = strategy;
   }
 
   public int executeStrategy(int num1, int num2){
      return strategy.doOperation(num1, num2);
   }
}

測試程式碼

public class StrategyPatternDemo {
   public static void main(String[] args) {
      StrategyControl control = new StrategyControl(new OperationAdd());    
      System.out.println("10 + 5 = " + control.executeStrategy(10, 5));
 
      control = new StrategyControl(new OperationSubtract());      
      System.out.println("10 - 5 = " + control.executeStrategy(10, 5));
   }
}
優點

策略模式的優點也很明顯,當我們的演算法策略發生變動時,我們只需要增加新的策略即可,而不需要修改策略實現之外的程式碼,程式碼的可擴充套件性又得到了極大的提升。

總結

好了,關於這三種設計模式,我們暫時就先說這麼多。

從我們總結的設計模式的優點來看,基本上所有的設計模式,都是為了提升我們系統的可擴張性,同時降低系統的耦合性,而且一定程度上減少了重複程式碼,當然也是我們要學習和應用設計模式的意義。

最後,大家需要著重關注的是策略模式和命令模式,這兩種設計模式是我們在業務開發中最可能能用到的,特別是策略模式,至於代理模式,我目前能想到的就是框架開發了,其他的我暫時還真想不到。