設計模式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();
    }
}

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