设计模式6——命令模式

如果饿了就吃,困了就睡,渴了就喝,人生就太无趣了


1 命令模式

1.1 概念

概念:将“请求”封装成对象,以便使用不同的请求、队列或日志来参数化其他对象。命令模式也支持撤销操作。
通过下面的引例来具体理解一下命令模式吧!!

1.2 引例

来分析一下顾客去餐厅点餐的例子。如图1:

  1. 顾客在订单上写下汉堡一个,薯条一包。调用createOrder()下单点餐。
  2. 服务员使用takeOrder()方法将顾客填好的订单带走。
  3. 服务员调用orderUp()通知厨师准备产品。
  4. 厨师拿到订单,看了内容,调用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:

  1. 客户(client)创建一个命令对象(Command),这个命令对象中包含接收者(Receiver)需要做的一组动作。

  2. 命令对象中提供了一个execute()方法,封装了需要接受者要做的动作。调用这些方法就会调用接受者的这些动作。

  3. 客户调用 调用者(Invoker)的setCommand(),并把命令对象传入该方法。

  4. 调用者调用命令对象的execute()方法。

  5. 最终接受者执行这些动作

在这里插入图片描述

1.4 命令模式类图

  • 将Command定义为接口,调用execute()方法会让接受者进行相关的动作。
  • Invoker中持有一个命令对象,并在某个时间点调用命令对象的execute(),将请求的实现。
  • 客户端负责创建一个ConcreteCommand,并设置其接受者。

在这里插入图片描述)

1.5 改进引例

(1) 类图

  • 将厨师的中的makeBurger()makeFries()抽象成Command,形成两个实现Command接口的类:CookMakeBurgerCommandCookMakeFriesCommand
  • 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();
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章