為了降低功能鍵與功能處理類之間的耦合度,讓用戶可以自定義每一個(gè)功能鍵的功能,Sunny 軟件公司開發(fā)人員使用命令模式來設(shè)計(jì)“自定義功能鍵”模塊,其核心結(jié)構(gòu)如圖 4 所示:
http://wiki.jikexueyuan.com/project/design-pattern-behavior/images/1366034181_4378.jpg" alt="自定義功能鍵核心結(jié)構(gòu)圖" />
在圖 4 中,F(xiàn)BSettingWindow 是“功能鍵設(shè)置”界面類,F(xiàn)unctionButton 充當(dāng)請(qǐng)求調(diào)用者,Command 充當(dāng)抽象命令類,MinimizeCommand 和 HelpCommand 充當(dāng)具體命令類,WindowHanlder 和 HelpHandler 充當(dāng)請(qǐng)求接收者。完整代碼如下所示:
import java.util.*;
//功能鍵設(shè)置窗口類
class FBSettingWindow {
private String title; //窗口標(biāo)題
//定義一個(gè)ArrayList來存儲(chǔ)所有功能鍵
private ArrayList<FunctionButton> functionButtons = new ArrayList<FunctionButton>();
public FBSettingWindow(String title) {
this.title = title;
}
public void setTitle(String title) {
this.title = title;
}
public String getTitle() {
return this.title;
}
public void addFunctionButton(FunctionButton fb) {
functionButtons.add(fb);
}
public void removeFunctionButton(FunctionButton fb) {
functionButtons.remove(fb);
}
//顯示窗口及功能鍵
public void display() {
System.out.println("顯示窗口:" + this.title);
System.out.println("顯示功能鍵:");
for (Object obj : functionButtons) {
System.out.println(((FunctionButton)obj).getName());
}
System.out.println("------------------------------");
}
}
//功能鍵類:請(qǐng)求發(fā)送者
class FunctionButton {
private String name; //功能鍵名稱
private Command command; //維持一個(gè)抽象命令對(duì)象的引用
public FunctionButton(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
//為功能鍵注入命令
public void setCommand(Command command) {
this.command = command;
}
//發(fā)送請(qǐng)求的方法
public void onClick() {
System.out.print("點(diǎn)擊功能鍵:");
command.execute();
}
}
//抽象命令類
abstract class Command {
public abstract void execute();
}
//幫助命令類:具體命令類
class HelpCommand extends Command {
private HelpHandler hhObj; //維持對(duì)請(qǐng)求接收者的引用
public HelpCommand() {
hhObj = new HelpHandler();
}
//命令執(zhí)行方法,將調(diào)用請(qǐng)求接收者的業(yè)務(wù)方法
public void execute() {
hhObj.display();
}
}
//最小化命令類:具體命令類
class MinimizeCommand extends Command {
private WindowHanlder whObj; //維持對(duì)請(qǐng)求接收者的引用
public MinimizeCommand() {
whObj = new WindowHanlder();
}
//命令執(zhí)行方法,將調(diào)用請(qǐng)求接收者的業(yè)務(wù)方法
public void execute() {
whObj.minimize();
}
}
//窗口處理類:請(qǐng)求接收者
class WindowHanlder {
public void minimize() {
System.out.println("將窗口最小化至托盤!");
}
}
//幫助文檔處理類:請(qǐng)求接收者
class HelpHandler {
public void display() {
System.out.println("顯示幫助文檔!");
}
}
配置文件 config.xml 中存儲(chǔ)了具體建造者類的類名,代碼如下所示:
<?xml version="1.0"?>
<config>
<className>HelpCommand</className>
<className>MinimizeCommand</className>
</config>
編寫如下客戶端測試代碼:
class Client {
public static void main(String args[]) {
FBSettingWindow fbsw = new FBSettingWindow("功能鍵設(shè)置");
FunctionButton fb1,fb2;
fb1 = new FunctionButton("功能鍵1");
fb2 = new FunctionButton("功能鍵1");
Command command1,command2;
//通過讀取配置文件和反射生成具體命令對(duì)象
command1 = (Command)XMLUtil.getBean(0);
command2 = (Command)XMLUtil.getBean(1);
//將命令對(duì)象注入功能鍵
fb1.setCommand(command1);
fb2.setCommand(command2);
fbsw.addFunctionButton(fb1);
fbsw.addFunctionButton(fb2);
fbsw.display();
//調(diào)用功能鍵的業(yè)務(wù)方法
fb1.onClick();
fb2.onClick();
}
}
編譯并運(yùn)行程序,輸出結(jié)果如下:
顯示窗口:功能鍵設(shè)置
顯示功能鍵:
功能鍵1
功能鍵1
------------------------------
點(diǎn)擊功能鍵:顯示幫助文檔!
點(diǎn)擊功能鍵:將窗口最小化至托盤!
如果需要修改功能鍵的功能,例如某個(gè)功能鍵可以實(shí)現(xiàn)“自動(dòng)截屏”,只需要對(duì)應(yīng)增加一個(gè)新的具體命令類,在該命令類與屏幕處理者(ScreenHandler)之間創(chuàng)建一個(gè)關(guān)聯(lián)關(guān)系,然后將該具體命令類的對(duì)象通過配置文件注入到某個(gè)功能鍵即可,原有代碼無須修改,符合“開閉原則”。在此過程中,每一個(gè)具體命令類對(duì)應(yīng)一個(gè)請(qǐng)求的處理者(接收者),通過向請(qǐng)求發(fā)送者注入不同的具體命令對(duì)象可以使得相同的發(fā)送者對(duì)應(yīng)不同的接收者,從而實(shí)現(xiàn)“將一個(gè)請(qǐng)求封裝為一個(gè)對(duì)象,用不同的請(qǐng)求對(duì)客戶進(jìn)行參數(shù)化”,客戶端只需要將具體命令對(duì)象作為參數(shù)注入請(qǐng)求發(fā)送者,無須直接操作請(qǐng)求的接收者。