如果餓了就喫,困了就睡,渴了就喝,人生就太無趣了
1 命令模式
1.1 概念
概念:將“請求”封裝成對象,以便使用不同的請求、隊列或日誌來參數化其他對象。命令模式也支持撤銷操作。
通過下面的引例來具體理解一下命令模式吧!!
1.2 引例
來分析一下顧客去餐廳點餐的例子。如圖1:
- 顧客在訂單上寫下漢堡一個,薯條一包。調用
createOrder()
下單點餐。 - 服務員使用
takeOrder()
方法將顧客填好的訂單帶走。 - 服務員調用
orderUp()
通知廚師準備產品。 - 廚師拿到訂單,看了內容,調用
makeHumburger()
和makeFries()
代碼實現
//廚師類
public class Cook {
public Cook() {}
public void makeBurger() {
System.out.println("Making a burger");
}
public void makeFries() {
System.out.println("Making fries");
}
}
//顧客類
public class Customer {
Waitress waitress;
public Customer(Waitress waitress) {
this.waitress = waitress;
}
public void hungry(Order o) {
System.out.println("服務員點餐");
order();
waitress.takeOrder(o);
}
public void order() {
System.out.println("我要漢堡和薯條");
}
}
//服務員類
public class Waitress {
Order order;
public Waitress() {
}
public void takeOrder(Order order) {
this.order = order;
order.orderUp();
}
}
//訂單接口
public interface Order {
public void orderUp();
}
//測試代碼
public class Diner {
public static void main(String[] args) {
Cook cook = new Cook();
Waitress waitress = new Waitress();
Customer customer = new Customer(waitress);
Order o = () -> {
cook.makeBurger();
cook.makeFries();
};
customer.hungry(o);
}
}
1.3 分析
從訂單生成到訂單結束,實際服務員不需要知道訂單內容,服務員的工作就是把訂單從顧客手中送到廚師手中。這個例子將請求提出者(顧客)與執行請求者(廚師)分開。這就是命令模式思路。
如圖2:
-
客戶(client)創建一個命令對象(Command),這個命令對象中包含接收者(Receiver)需要做的一組動作。
-
命令對象中提供了一個
execute()
方法,封裝了需要接受者要做的動作。調用這些方法就會調用接受者的這些動作。 -
客戶調用 調用者(Invoker)的
setCommand()
,並把命令對象傳入該方法。 -
調用者調用命令對象的
execute()
方法。 -
最終接受者執行這些動作
1.4 命令模式類圖
- 將Command定義爲接口,調用
execute()
方法會讓接受者進行相關的動作。 Invoker
中持有一個命令對象,並在某個時間點調用命令對象的execute()
,將請求的實現。- 客戶端負責創建一個
ConcreteCommand
,並設置其接受者。
)
1.5 改進引例
(1) 類圖
- 將廚師的中的
makeBurger()
和makeFries()
抽象成Command
,形成兩個實現Command
接口的類:CookMakeBurgerCommand
和CookMakeFriesCommand
。 - 將
waitress
抽象成Invoker
。通過takeOrder()
方法調用Command
接口的execute()
方法。
(2) 代碼
public interface Order {
public void execute();
}
public class CookMakeFriesCommand implements Order {
private Cook cook;
public CookMakeFriesCommand(Cook cook) {
this.cook = cook;
}
@Override
public void execute() {
cook.makeFries();
}
}
public class CookMakeBurgerCommand implements Order {
private Cook cook;
public CookMakeBurgerCommand(Cook cook) {
this.cook = cook;
}
@Override
public void execute() {
cook.makeBurger();
}
}
public class Cook {
public Cook() {}
public void makeBurger() {
System.out.println("Making a burger");
}
public void makeFries() {
System.out.println("Making fries");
}
}
public class Customer {
Waitress waitress;
public Customer(Waitress waitress) {
this.waitress = waitress;
}
public void hungry(Order o) {
System.out.println("服務員點餐");
waitress.takeOrder(o);
}
}
public class Waitress {
Order order;
public Waitress() {
}
private void setOrder(Order order){
this.order=order;
}
public void takeOrder(Order order) {
setOrder(order);
order.execute();
}
}
public class Diner {
public static void main(String[] args) {
Cook cook = new Cook();
Waitress waitress = new Waitress();
Customer customer = new Customer(waitress);
CookMakeFriesCommand friesCommand=new CookMakeFriesCommand(cook);
CookMakeBurgerCommand burgerCommand=new CookMakeBurgerCommand(cook);
customer.hungry(friesCommand);
customer.hungry(burgerCommand);
}
}
2. 實例練習(遙控器)
需要爲智能家居的遙控器設計API,來控制各種的智能家居。先以電燈和車庫門爲例進行設計。
2.1 類圖
通過這個例子就可以看到,當一個對象的方法較多時,生成了的命令類也就相應的多了起來,這就是命令模式的缺點。
2.2 代碼
public class GarageDoor {
public GarageDoor() {
}
public void up() {
System.out.println("Garage Door is Open");
}
public void down() {
System.out.println("Garage Door is Closed");
}
public void stop() {
System.out.println("Garage Door is Stopped");
}
public void lightOn() {
System.out.println("Garage light is on");
}
public void lightOff() {
System.out.println("Garage light is off");
}
}
public class Light {
public Light() {
}
public void on() {
System.out.println("Light is on");
}
public void off() {
System.out.println("Light is off");
}
}
public interface Command {
void execute();
}
public class GarageDoorDownCommand implements Command {
GarageDoor garageDoor;
public GarageDoorDownCommand(GarageDoor garageDoor) {
this.garageDoor = garageDoor;
}
@Override
public void execute() {
garageDoor.down();
}
}
public class GarageDoorLightOffCommand implements Command {
GarageDoor garageDoor;
public GarageDoorLightOffCommand(GarageDoor garageDoor) {
this.garageDoor = garageDoor;
}
@Override
public void execute() {
garageDoor.lightOff();
}
}
public class GarageDoorOpenCommand implements Command {
GarageDoor garageDoor;
public GarageDoorOpenCommand(GarageDoor garageDoor) {
this.garageDoor = garageDoor;
}
public void execute() {
garageDoor.up();
}
}
public class GarageDoorStopCommand implements Command {
GarageDoor garageDoor;
public GarageDoorStopCommand(GarageDoor garageDoor) {
this.garageDoor = garageDoor;
}
@Override
public void execute() {
garageDoor.stop();
}
}
public class GarageLightOnCommand implements Command {
GarageDoor garageDoor;
public GarageLightOnCommand(GarageDoor garageDoor) {
this.garageDoor = garageDoor;
}
@Override
public void execute() {
garageDoor.lightOn();
}
}
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 slot;
public SimpleRemoteControl() {}
public void setCommand(Command command) {
slot = command;
}
public void buttonWasPressed() {
slot.execute();
}
}
public class RemoteControlTest {
public static void main(String[] args) {
SimpleRemoteControl remote = new SimpleRemoteControl();
Light light = new Light();
GarageDoor garageDoor = new GarageDoor();
LightOnCommand lightOn = new LightOnCommand(light);
GarageDoorOpenCommand garageOpen = new GarageDoorOpenCommand(garageDoor);
GarageDoorDownCommand garageDoorDownCommand = new GarageDoorDownCommand(garageDoor);
GarageDoorStopCommand garageDoorStopCommand = new GarageDoorStopCommand(garageDoor);
GarageDoorLightOffCommand garageDoorLightOffCommand = new GarageDoorLightOffCommand(garageDoor);
GarageLightOnCommand garageLightOnCommand = new GarageLightOnCommand(garageDoor);
remote.setCommand(garageOpen);
remote.buttonWasPressed();
remote.setCommand(garageLightOnCommand);
remote.buttonWasPressed();
remote.setCommand(garageDoorStopCommand);
remote.buttonWasPressed();
remote.setCommand(garageDoorDownCommand);
remote.buttonWasPressed();
remote.setCommand(garageDoorLightOffCommand);
remote.buttonWasPressed();
remote.setCommand(lightOn);
remote.buttonWasPressed();
}
}