您好,登錄后才能下訂單哦!
文章首發(fā):
行為型模式:命令模式
十一大行為型模式之三:命令模式。
姓名 :命令模式
英文名 :Command Pattern
價(jià)值觀 :軍令如山
個(gè)人介紹 :
Encapsulate a request as an object,thereby letting you parameterize clients with different requests,queue or log requests,and support undoable operations.
將一個(gè)請(qǐng)求封裝成一個(gè)對(duì)象,從而讓你使用不同的請(qǐng)求把客戶(hù)端參數(shù)化,對(duì)請(qǐng)求排隊(duì)或者記錄請(qǐng)求日志,可以提供命令的撤銷(xiāo)和恢復(fù)功能。
(來(lái)自《設(shè)計(jì)模式之禪》)
作為一個(gè)程序猿,我們每天都在經(jīng)歷著命令模式,技術(shù)經(jīng)理把需求任務(wù)分配給工程師開(kāi)發(fā),有時(shí)因?yàn)榈谌交蛘咂渌豢煽咕艿囊蛩貙?dǎo)致需求停止開(kāi)發(fā)。這種工作模式就是命令模式。好了,開(kāi)始故事了。小明在 XX 科技公司做一個(gè)安靜的程序猿,有一天技術(shù)經(jīng)理給他分配了一個(gè)任務(wù):新增黑名單,也就是在他們系統(tǒng)的某個(gè)模塊里面可以手工對(duì)電話(huà)打黑名單標(biāo)簽的功能。小明接到任務(wù)后就立馬開(kāi)發(fā),在開(kāi)發(fā)了 2 天之后,因?yàn)閼?zhàn)略原因,技術(shù)經(jīng)理大明暫停了這個(gè)開(kāi)發(fā)任務(wù),接下來(lái)我們通過(guò)非命令模式和命令模式 2 種代碼實(shí)現(xiàn)來(lái)體現(xiàn)這個(gè)過(guò)程。在這個(gè)場(chǎng)景中,為了簡(jiǎn)單,我們假定技術(shù)經(jīng)理大明手下只有小明一個(gè)開(kāi)發(fā)人員。
非命令模式也就是不使用命令模式的代碼實(shí)現(xiàn)。代碼中,我們出現(xiàn)了 Developer 開(kāi)發(fā)人,開(kāi)發(fā)同學(xué)是接受技術(shù)經(jīng)理傳達(dá)的任務(wù),技術(shù)經(jīng)理讓他開(kāi)發(fā)哪個(gè)需求就開(kāi)發(fā)哪個(gè)需求,如果項(xiàng)目有問(wèn)題需要中斷,也需要技術(shù)經(jīng)理評(píng)估后傳達(dá)給開(kāi)發(fā)同學(xué),所以 Developer 有 2 個(gè)方法,分別是 develop() 開(kāi)發(fā)需求和 suspend() 暫停需求。 Requirement 則為需求類(lèi),TechnicalManager1 則為技術(shù)經(jīng)理類(lèi),他有一個(gè)方法 action(),通過(guò)這個(gè)方法來(lái)指定開(kāi)發(fā)同學(xué)開(kāi)發(fā)任務(wù)或者暫停任務(wù)。
public class NoCommandTest {
public static void main(String[] args) {
Developer xiaoMing = new Developer("小明");
Requirement requirement = new Requirement("新增黑名單");
TechnicalManager1 technicalManager2 = new TechnicalManager1("大明");
technicalManager2.setDeveloper(xiaoMing);
technicalManager2.action(requirement, "develop");
System.out.println("開(kāi)發(fā)了 2 天,需求變故,需要暫停。。。");
technicalManager2.action(requirement, "suspend");
}
}
/**
* 開(kāi)發(fā)人員
*/
class Developer {
private String name;
public Developer(String name) {
this.name = name;
}
public void develop(Requirement requirement) {
System.out.println(this.name + " 開(kāi)始開(kāi)發(fā)需求:" + requirement.getName());
}
public void suspend(Requirement requirement) {
System.out.println(this.name + " 停止開(kāi)發(fā)需求:" + requirement.getName());
}
public String getName() {
return name;
}
}
/**
* 需求
*/
class Requirement {
private String name;
public Requirement(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
/**
* 技術(shù)經(jīng)理
*/
class TechnicalManager1 {
private String name;
private Developer developer;
public TechnicalManager1(String name) {
this.name = name;
}
public void setDeveloper(Developer developer) {
this.developer = developer;
}
public void action(Requirement requirement, String type) {
if ("develop".equals(type)) {
this.developer.develop(requirement);
} else if ("suspend".equals(type)) {
this.developer.suspend(requirement);
}
}
}
打印結(jié)果:
小明 開(kāi)始開(kāi)發(fā)需求:新增黑名單
開(kāi)發(fā)了 2 天,需求變故,需要暫停。。。
小明 停止開(kāi)發(fā)需求:新增黑名單
通過(guò)代碼,我們可以發(fā)現(xiàn)技術(shù)經(jīng)理和開(kāi)發(fā)同學(xué)是強(qiáng)依賴(lài)關(guān)系。如果技術(shù)經(jīng)理下達(dá)了一個(gè)任務(wù),要求小明寫(xiě)一下周報(bào),這時(shí)候得怎么寫(xiě)?是不是小明需要一個(gè)寫(xiě)周報(bào)的方法,大明也需要新增一個(gè)處理事務(wù)類(lèi)型?有沒(méi)有更好的方法讓技術(shù)經(jīng)理不需要做任何改變?命令模式就來(lái)解決這個(gè)問(wèn)題。
在這個(gè)例子中,不管大明叫小明做什么事情,其實(shí)都是一樣的,就是下達(dá)任務(wù)命令,讓小明去執(zhí)行命令。我們可以利用命令模式把下達(dá)任務(wù)這個(gè)抽象起來(lái),當(dāng)做父類(lèi),下達(dá)開(kāi)發(fā)命令、下達(dá)暫停命令、下達(dá)寫(xiě)周報(bào)等等都是不同的子命令。代碼如下。
public class CommandTest {
public static void main(String[] args) {
Developer xiaoMing = new Developer("小明");
Command developCommand = new DevelopCommand(xiaoMing);
Command suspendCommand = new SuspendCommand(xiaoMing);
Requirement requirement = new Requirement("新增黑名單");
TechnicalManager2 technicalManager = new TechnicalManager2("大明");
technicalManager.setCommand(developCommand);
technicalManager.action(requirement);
System.out.println("開(kāi)發(fā)了 2 天,需求變故,需要暫停。。。");
technicalManager.setCommand(suspendCommand);
technicalManager.action(requirement);
}
}
/**
* 命令
*/
abstract class Command {
protected Developer developer;
public Command(Developer developer) {
this.developer = developer;
}
public abstract void execute(Requirement requirement);
}
/**
* 開(kāi)始開(kāi)發(fā)
*/
class DevelopCommand extends Command {
public DevelopCommand(Developer developer) {
super(developer);
}
@Override
public void execute(Requirement requirement) {
this.developer.develop(requirement);
}
}
/**
* 開(kāi)發(fā)中斷
*/
class SuspendCommand extends Command {
public SuspendCommand(Developer developer) {
super(developer);
}
@Override
public void execute(Requirement requirement) {
this.developer.suspend(requirement);
}
}
/**
* 技術(shù)經(jīng)理
*/
class TechnicalManager2 {
private String name;
private Command command;
public TechnicalManager2(String name) {
this.name = name;
}
public void action(Requirement requirement) {
this.command.execute(requirement);
}
public void setCommand(Command command) {
this.command = command;
}
}
打印結(jié)果:
小明 開(kāi)始開(kāi)發(fā)需求:新增黑名單
開(kāi)發(fā)了 2 天,需求變故,需要暫停。。。
小明 停止開(kāi)發(fā)需求:新增黑名單
代碼中用 Command 來(lái)抽象下達(dá)任務(wù),而技術(shù)經(jīng)理 TechnicalManager2 并沒(méi)有和 Developer 有直接的關(guān)系,而是 TechnicalManager2 和 Command 建立的聯(lián)系,Command 和 Developer 建立了聯(lián)系。這樣子把大明和小明的強(qiáng)依賴(lài)關(guān)系給剝離開(kāi),而新增一個(gè)下達(dá)寫(xiě)周報(bào)的任務(wù)也很簡(jiǎn)單,在 Developer 中新增一個(gè)處理寫(xiě)周報(bào)的方法,新增一個(gè)寫(xiě)周報(bào)的 Command 子類(lèi),就可以了,TechnicalManager2 如上面所愿不用修改。這就是完整的一個(gè)命令模式代碼。
代碼:
Command Pattern
從文章中我們就可以看到,利用命令模式能夠進(jìn)行類(lèi)的解耦,讓調(diào)用者和接受者沒(méi)有任何關(guān)系,也通過(guò)對(duì)行為的抽象,讓新增其他行為變得清晰容易,也就是可擴(kuò)展性大大增加。
推薦閱讀:
創(chuàng)建型模式:?jiǎn)卫J剑ㄐ∶骶椭挥?1 輛車(chē))
創(chuàng)建型模式:工廠方法(小明家的車(chē)庫(kù))
創(chuàng)建型模式:抽象工廠(寶馬車(chē)就得用寶馬輪胎和寶馬方向盤(pán))
創(chuàng)建型模式:建造者模式(湯這么煲)
創(chuàng)建型模式:原型模式(復(fù)印書(shū)籍)
行為型模式:模板方法(運(yùn)動(dòng)鞋制造過(guò)程)
行為型模式:中介者模式(租房找中介)
公眾號(hào)后臺(tái)回復(fù)『大禮包』獲取 Java、Python、IOS 等教程
加個(gè)人微信備注『教程』獲取架構(gòu)師、機(jī)器學(xué)習(xí)等教程
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。