摘要
本學期我學習了“設計模式-可復用面向對象軟件的基礎”這門課程,這次我采用的是命令模式+策略模式兩種設計模式結合的案例。
分析的案例為:遙控器控制天花板上的吊扇,它有多種轉動速度,當然也允許被關閉。假設吊扇速度:高、中、低 、關閉。采用安全模式+策略設計模式。
報告整體結構為:兩種設計模式的分析、理解,類圖,實例分析、代碼分析,總結。
目錄
第一章 命令模式+策略模式 1
1.1 命令模式 1
1.1.1 定義 1
1.1.2 命令模式的結構 1
1.1.3 角色 1
1.1.4 優點 2
1.1.5 缺點 2
1.1.6 適用情況 2
1.2 策略模式 2
1.2.1意圖 2
1.2.2 主要解決問題 2
1.2.4 如何解決 3
1.2.5 關鍵代碼 3
1.2.6優點 3
1.2.7 缺點 3
1.2.8 使用場景 3
1.2.9 注意事項 3
第二章 案例分析 4
2.1 類圖 4
2.2 測試分析 4
2.3 代碼分析 5
2.3.1 命令模式模塊代碼 6
2.3.2 策略模式模塊代碼 9
第三章 總結 12
第一章 命令模式+策略模式
本案例用到的兩種案例為安全模式+策略模式,因此在分析案例之前我先對兩種設計模式進行分析。命令模式具體實現命令調控,策略模式定義一系列的算法,把它們一個個封裝起來。
1.1 命令模式
1.1.1 定義
將來自客戶端的請求傳入一個對象,從而使你可用不同的請求對客戶進行參數化。用於“行為請求者”與“行為實現者”解耦,可實現二者之間的松耦合,以便適應變化。分離變化與不變的因素。
1.1.2 命令模式的結構
命令模式是對命令的封裝。命令模式把發出命令的責任和執行命令的責任分割開,委派給不同的對象。
每一個命令都是一個操作:請求的一方發出請求要求執行一個操作;接收的一方收到請求,並執行操作。命令模式允許請求的一方和接收的一方獨立開來,使得請求的一方不必知道接收請求的一方的接口,更不必知道請求是怎么被接收,以及操作是否被執行、何時被執行,以及是怎么被執行的。
1.1.3 角色
Command
定義命令的接口,聲明執行的方法。
ConcreteCommand
命令接口實現對象,是“虛”的實現;通常會持有接收者,並調用接收者的功能來完成命令要執行的操作。
Receiver
接收者,真正執行命令的對象。任何類都可能成為一個接收者,只要它能夠實現命令要求實現的相應功能。
Invoker
要求命令對象執行請求,通常會持有命令對象,可以持有很多的命令對象。這個是客戶端真正觸發命令並要求命令執行相應操作的地方,也就是說相當於使用命令對象的入口。
Client
創建具體的命令對象,並且設置命令對象的接收者。注意這個不是我們常規意義上的客戶端,而是在組裝命令對象和接收者,或許,把這個Client稱為裝配者會更好理解,因為真正使用命令的客戶端是從Invoker來觸發執行。
1.1.4 優點
1.降低對象之間的耦合度。
2.新的命令可以很容易地加入到系統中。
3.可以比較容易地設計一個組合命令。
4.調用同一方法實現不同的功能
1.1.5 缺點
使用命令模式可能會導致某些系統有過多的具體命令類。因為針對每一個命令都需要設計一個具體命令類,因此某些系統可能需要大量具體命令類,這將影響命令模式的使用。
1.1.6 適用情況
1.系統需要將請求調用者和請求接收者解耦,使得調用者和接收者不直接交互。
2.系統需要在不同的時間指定請求、將請求排隊和執行請求。
3.系統需要支持命令的撤銷(Undo)操作和恢復(Redo)操作。
4.系統需要將一組操作組合在一起,即支持宏命令。
1.2 策略模式
1.2.1意圖
定義一系列的算法,把它們一個個封裝起來, 並且使它們可相互替換。
1.2.2 主要解決問題
在有多種算法相似的情況下,使用 if...else 所帶來的復雜和難以維護。
1.2.3 何時使用
一個系統有許多許多類,而區分它們的只是他們直接的行為。
1.2.4 如何解決
將這些算法封裝成一個一個的類,任意地替換。
1.2.5 關鍵代碼
實現同一個接口。
應用實例: 1、諸葛亮的錦囊妙計,每一個錦囊就是一個策略。 2、旅行的出游方式,選擇騎自行車、坐汽車,每一種旅行方式都是一個策略。 3、JAVA AWT 中的 LayoutManager。
1.2.6優點
1、算法可以自由切換。
2、避免使用多重條件判斷。
3、擴展性良好。
1.2.7 缺點
1、策略類會增多。
2、所有策略類都需要對外暴露。
1.2.8 使用場景
1、如果在一個系統里面有許多類,它們之間的區別僅在於它們的行為,那么使用策略模式可以動態地讓一個對象在許多行為中選擇一種行為。
2、一個系統需要動態地在幾種算法中選擇一種。
3、如果一個對象有很多的行為,如果不用恰當的模式,這些行為就只好使用多重的條件選擇語句來實現。
1.2.9 注意事項
如果一個系統的策略多於四個,就需要考慮使用混合模式,解決策略類膨脹的問題。
第二章 案例分析
本文分析的案例為:遙控器控制天花板上的吊扇,它有多種轉動速度,當然也允許被關閉。假設吊扇速度:高、中、低 、關閉。采用安全模式+策略設計模式。
2.1 類圖
2.2 測試分析
本案例運行測試如下,通過控制高檔,中檔,低檔,三個命令來控制分扇轉動的速度,如圖2-1,2-2,2-3所示
圖2-1 高檔風速命令
圖2-2 中檔風速命令
圖2-3 低檔風速命令
2.3 代碼分析
本案例以先以命令模式實現三個命令,再以策略模式定義算法實現,具體實現代碼如下:
2.3.1 命令模式模塊代碼
1.Command類 執行命令的接口
package command;
public interface Command {
public String execute();
public String undo();
}
2.NoCommand類
package command;
public class NoCommand implements Command{
public String undo() {
return null;
}
@Override
public String execute() {
return null;
}
}
3.RemoteLoader類 加載
package command;
import java.awt.Color;
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollBar;
public class RemoteLoader extends JFrame implements ActionListener {
private JButton high;
private JButton middle;
private JButton low;
private JLabel text;
public RemoteLoader() {
super("設計模式");
setSize(300, 200);
setVisible(true);
Container pane = getContentPane();
FlowLayout flo = new FlowLayout();
pane.setLayout(flo);
high = new JButton("高檔");
high.addActionListener(this);
middle = new JButton("中檔");
middle.addActionListener(this);
text = new JLabel();
low = new JButton("低檔");
low.addActionListener(this);
pane.add(high);
pane.add(middle);
pane.add(low);
pane.add(text);
setContentPane(pane);
setVisible(true);
}
public void actionPerformed(ActionEvent e) {
if (e.getSource() == high) {
high.setBackground(Color.cyan);
Context1 context1 = new Context1(new OperationGao1());
String executeStrategygao = context1.executeStrategy();
System.out.println(executeStrategygao);
text.setText(executeStrategygao);
middle.setBackground(null);
low.setBackground(null);
}
if (e.getSource() == middle) {
middle.setBackground(Color.cyan);
Context1 context1 = new Context1(new OperationGao1());
context1 = new Context1(new OperationZhong1());
String executeStrategyzhong = context1.executeStrategy();
System.out.println(executeStrategyzhong);
text.setText(executeStrategyzhong);
high.setBackground(null);
low.setBackground(null);
}
if (e.getSource() == low) {
low.setBackground(Color.cyan);
Context1 context1 = new Context1(new OperationGao1());
context1 = new Context1(new OperationDi1());
String executeStrategylow = context1.executeStrategy();
System.out.println(executeStrategylow);
text.setText(executeStrategylow);
high.setBackground(null);
middle.setBackground(null);
}
}
}
4.RemoteControl 類
package command;
public class RemoteControl {
Command command;
public RemoteControl () {
Command noCommand = new NoCommand();
command = noCommand;
}
public void setCommand(Command command) {
this.command = command;
}
public String buttonWasPushed() {
return command.execute();
}
public void undoButtonWasPushed() {
command.undo();
}
}
5.GaoCommand 類 高風速命令
package command;
public class GaoCommand implements Command {
@Override
public String execute() {
// TODO Auto-generated method stub
return "高風擋已經打開";
}
@Override
public String undo() {
// TODO Auto-generated method stub
return "Gaocommand undo";
}
}
6.ZhongCommand 類 中風速命令
package command;
public class ZhongCommand implements Command {
@Override
public String execute() {
return "中風擋已經打開";
}
@Override
public String undo() {
// TODO Auto-generated method stub
return "Zhongcommand undo";
}
}
7.DiCommand 類 低風速命令
package command;
public class DiCommand implements Command {
@Override
public String execute() {
// TODO Auto-generated method stub
return "低風擋已經打開";
}
@Override
public String undo() {
// TODO Auto-generated method stub
return "Dicommand undo";
}
}
2.3.2 策略模式模塊代碼
1.Strategy1類 創建一個接口:
package command;
public interface Strategy1 {
public String doOperation();
}
2.OperationGao1類 實現接口的高風速實體類
package command;
import command.Command;
import command.GaoCommand;
import command.RemoteControl;
public class OperationGao1 implements Strategy1{
@Override
public String doOperation() {
RemoteControl rc = new RemoteControl();
Command gaoCommand = new GaoCommand();
rc.setCommand(gaoCommand);
return rc.buttonWasPushed();
}
}
3.OperationZhong1類 實現接口的中風速實體類
package command;
import command.Command;
import command.RemoteControl;
import command.ZhongCommand;
public class OperationZhong1 implements Strategy1 {
@Override
public String doOperation() {
// TODO Auto-generated method stub
RemoteControl rc = new RemoteControl();
Command zhongCommand = new ZhongCommand();
rc.setCommand(zhongCommand);
return rc.buttonWasPushed();
}
}
3.OperationDi1類 實現接口的低風速實體類
package command;
import command.Command;
import command.DiCommand;
import command.RemoteControl;
public class OperationDi1 implements Strategy1 {
@Override
public String doOperation() {
RemoteControl rc = new RemoteControl();
Command diCommand = new DiCommand();
rc.setCommand(diCommand);
return rc.buttonWasPushed();
}
}
4.Context1類
package command;
public class Context1 {
private Strategy1 strategy1;
public Context1(Strategy1 strategy1){
this.strategy1 = strategy1;
}
public String executeStrategy(){
return strategy1.doOperation();
}
}
第三章 總結
首先真誠的感謝郭老師的認真講解,同學們的熱心幫助,讓我學到了很多。剛開始學習設計模式的時候,感到這些模式真的非常抽象。后來隨着郭老師的講解,以及在同學們的幫助下我慢慢學會了一些設計模式,簡單理解了設計模式的概念。
在本次的作業中,我使用的是含有命令模式和策略模式的案例。經過這次的作業,不僅讓我多這兩種模式有了很好的理解,更重要的是我對整個設計模式都有了一定的了解。
命令模式就是將來自客戶端的請求傳入一個對象,從而使你可用不同的請求對客戶進行參數化。用於“行為請求者”與“行為實現者”解耦,可實現二者之間的松耦合,以便適應變化。策略模式就是定義一系列的算法,把它們一個個封裝起來, 並且使它們可相互替換。
設計模式,它給出了很多設計中的技巧與思路,對於很多優秀的設計,它加以總結與提煉。設計模式並非四人團拍腦瓜想出來的,而是他們搜集了其他人優秀的設計,加以整理出來的。
應用設計模式會給我們帶來很多好處:軟件將變得更加靈活,模塊之間的耦合度將會降低,效率會提升,開銷會減少。更重要的,設計模式就好像美聲唱法中的花腔,讓你的設計更加漂亮。總的來說,設計模式似乎將軟件設計提升到藝術的層次。
設計模式已經被廣泛的應用了,在現在很多的圖形界面框架都使用了MVC模式,大量跌代器模式的應用,徹底改變了我們對集合的操作方式。不僅如此,應用了設計模式的設計,往往被看成為優秀的設計。
最后再一次感謝郭老師為我們講解設計模式,郭老師也一直在和我們一起學習,一起進步,希望您身體健康,家庭幸福。