這就是命令,命令模式
0x01:命令模式簡(jiǎn)介
在軟件設(shè)計(jì)中,我們經(jīng)常需要向某些對(duì)象發(fā)送請(qǐng)求,但是并不知道請(qǐng)求的接收者是誰,也不知道被請(qǐng)求的操作是哪個(gè), 我們只需在程序運(yùn)行時(shí)指定具體的請(qǐng)求接收者即可,此時(shí),可以使用命令模式來進(jìn)行設(shè)計(jì)。
命令模式:請(qǐng)求以命令的形式包裹在對(duì)象中,并傳給調(diào)用對(duì)象。調(diào)用對(duì)象尋找可以處理該命令的合適的對(duì)象,并把該命令傳給相應(yīng)的對(duì)象,該對(duì)象執(zhí)行命令。
UML類圖如下:

主要角色分析如下:
Invoker:調(diào)用者,要求該命令執(zhí)行這個(gè)請(qǐng)求,通常會(huì)持有命令對(duì)象,可以持有多個(gè)命令對(duì)象。這個(gè)是客戶端真正觸發(fā)命令并要求命令執(zhí)行相應(yīng)操作的地方,也就是相當(dāng)于使用命令對(duì)象的入口。
Command:抽象命令,需要執(zhí)行的所有命令都在這里聲明,可以是接口或抽象類;
Receiver:接收者,真正執(zhí)行命令的對(duì)象。知道如何實(shí)施與執(zhí)行一個(gè)請(qǐng)求相關(guān)的操作,任何類都可能作為一個(gè)接收者,只要它能夠?qū)崿F(xiàn)命令要求實(shí)現(xiàn)的相應(yīng)功能。
ConcreteCommand:命令接口實(shí)現(xiàn)對(duì)象,是“虛”的實(shí)現(xiàn);通常會(huì)持有接收者,并調(diào)用接收者的功能來完成命令要執(zhí)行的操作。
Client:創(chuàng)建具體的命令對(duì)象,并且設(shè)置命令對(duì)象的接收者。注意這個(gè)不是常規(guī)意義上的客戶端,而是在組裝命令對(duì)象和接收者。或許把這個(gè)Client稱為裝配者會(huì)更好理解,因?yàn)檎嬲褂妹畹目蛻舳耸菑腎nvoker來觸發(fā)執(zhí)行。
0x02:命令模式的實(shí)現(xiàn)
Receiver:該角色就是干活的角色, 命令傳遞到這里就應(yīng)該被執(zhí)行
public?class?Receiver?{
????public?void?action()?{
????????System.out.println("命令執(zhí)行了~~~");
????}
}
Command:聲明執(zhí)行操作的接口/抽象類
public?abstract?class?Command?{
????protected?Receiver?receiver;
????public?Command(Receiver?receiver)?{
????????this.receiver?=?receiver;
????}
????//執(zhí)行命令的方法
????abstract?public?void?execute();
}
ConcreteCommand類:具體的Command,用于構(gòu)造傳遞接收者,根據(jù)場(chǎng)景需求,具體的命令類也可能有多個(gè)
public?class?ConcreteCommand?extends?Command?{
????//構(gòu)造傳遞接收者
????public?ConcreteCommand(Receiver?receiver)?{
????????super(receiver);
????}
????//必須實(shí)現(xiàn)一個(gè)命令
????@Override
????public?void?execute()?{
????????receiver.action();
????}
}
Invoker類:接收命令,并執(zhí)行命令
public?class?Invoker?{
????private?Command?command;
????//接收命令
????public?void?setCommand(Command?command)?{
????????this.command?=?command;
????}
????//執(zhí)行命令
????public?void?executeCommand()?{
????????command.execute();
????}
}
命令模式測(cè)試代碼:首先定義一個(gè)接收者,然后定義一個(gè)命令用于發(fā)送給接收者,最后再聲明一個(gè)調(diào)用者,即可把命令交給調(diào)用者執(zhí)行
public?class?Client?{
????public?static?void?main(String[]?args)?{
????????//定義接收者
????????Receiver?receiver?=?new?Receiver();
????????//定義一個(gè)發(fā)送給接收者的命令
????????Command?command?=?new?ConcreteCommand(receiver);
????????//聲明調(diào)用者
????????Invoker?invoker?=?new?Invoker();
????????//把命令交給調(diào)用者執(zhí)行
????????invoker.setCommand(command);
????????//執(zhí)行命令
????????invoker.executeCommand();
????}
}
0x03:命令模式在JDK與開源框架中的運(yùn)用
多線程中的java.lang.Runable
JDK中的Runnable接口,Runnable 相當(dāng)于命令模式中的抽象命令角色(Command)。Runnabl 中的run()方法就當(dāng)于execute()方法。
@FunctionalInterface
public?interface?Runnable?{
????public?abstract?void?run();
}
只要是實(shí)現(xiàn)了Runnable接口的類都被認(rèn)為是一個(gè)線程,相當(dāng)于命令模式中的具體命令角色(ConcreteCommand)
Thread就是調(diào)用者(Invoker),提供了start,join,interrupt等方法來控制“命令”也就是Runnable的執(zhí)行。而Receiver則是讓程序員可以自由與Runnale組合的抽象。
實(shí)際上調(diào)用線程的start()方法之后,就有資格去爭(zhēng)搶CPU資源,而不需要編寫獲得CPU資源的邏輯。而線程搶到CPU資源后,就會(huì)執(zhí)行run()方法中的內(nèi)容,用Runnable接口把用戶請(qǐng)求和CPU執(zhí)行進(jìn)行解耦。
工作流引擎Activiti
Activiti是一款優(yōu)秀開源軟件,通過閱讀源碼,不但可以了解工作流引擎執(zhí)行的原理,還可以增加個(gè)人的編碼功力。Activiti所有執(zhí)行過程都是采用命令模式進(jìn)行執(zhí)行。?

喜歡,在看
