如果饿了就吃,困了就睡,渴了就喝,人生就太无趣了
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();
}
}