定义
将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录日志请求,以及支持可撤销的操作。
结构图
书上的结构图 网友的理解图使用场景
- 优点:
- 它能较容易地设计一个命令队列;
- 在需要的情况下,可以较容易地将命令记入日志;
- 允许接收请求的一方决定是否要否决请求;
- 可以容易地实现对请求的撤销和重做;
- 由于加进新的具体命令类不影响其他的类,因此增加新的具体命令类很容易。
关键优点:命令模式把请求一个操作的对象与知道怎么执行一个操作的对象分割开。
- 敏捷开发原则告诉我们,不要为代码添加基于猜测的、实际不需要的功能。如果不清楚一个系统是否需要命令模式,一般就不要着急去实现它,事实上,在需要的时候通过重构实现这个模式并不困难,只有在真正需要如撤销/恢复操作等功能时,把原来的代码重构为命令模式才有意义。
烤肉店的例子
- 结构图
- Barbecue;执行者;Receiver
/**
* 烧烤师傅; Receiver; 具体的执行者
*/
class Barbecue {
// 烤羊肉串
public String bakeMutton() {
return "烤羊肉串!";
}
// 烤鸡翅
public String bakeChickenWing() {
return "烤鸡翅!";
}
}
- Command;命令抽象父类
/**
* 命令抽象父类
*/
abstract class Command {
public String name = "未定义";
protected Barbecue receiver;
Command(Barbecue receiver) {
this.receiver = receiver;
}
abstract String executeCommand();
}
- 具体的命令类,ConcreteCommand
/**
* 具体的烤羊肉串命令,通知烤肉者
*/
class MuttonCommand extends Command {
MuttonCommand(Barbecue receiver) {
super(receiver);
name = "烤羊肉";
}
@Override
String executeCommand() {
return receiver.bakeMutton();
}
}
/**
* 具体的烤鸡翅命令,通知烤肉者
*/
class ChickenCommand extends Command {
ChickenCommand(Barbecue receiver) {
super(receiver);
name = "烤鸡翅";
}
@Override
String executeCommand() {
return receiver.bakeChickenWing();
}
}
/**
* 具体的命令;新产品;暂时还不执行
*/
class NewCommand extends Command {
NewCommand(Barbecue receiver) {
super(receiver);
name = "new";
}
@Override
String executeCommand() {
// 新产品,还未开发
return "";
}
}
- Waiter;(Invoker);调用者
class Waiter {
// 命令的集合
private ArrayList<Command> orders = new ArrayList<Command>();
// 日志
private String log = "";
// 下单
public void setOrder(Command command) {
if ("new" == command.name) {
log += "服务员:新产品还没有推出,请点别的烧烤。\n";
} else {
orders.add(command);
log += "增加订单:" + command.name + " === 时间:"
+ getCurrentTimeString() + "\n";
}
}
// 取消订单
public void cancelOrder(Command command) {
if (orders.contains(command)) {
orders.remove(command);
log += "取消订单:" + command.name + " === 时间:"
+ getCurrentTimeString() + "\n";
}
}
// 通知执行
public void notice() {
for (Command command:
orders) {
log += command.executeCommand() + "\n";
}
}
// 显示日志
public String show() {
return log;
}
// 重置
public void reset() {
orders.clear();
log = "";
}
// 下单时间
private String getCurrentTimeString() {
Date date = new Date();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy年-MM月dd日-HH时mm分ss秒 E");
return dateFormat.format(date);
}
}
- 测试界面
- 客户端程序
public class CommandActivity extends AppCompatActivity {
public static void launch(Context context) {
if (null != context) {
Intent intent = new Intent();
intent.setClass(context, CommandActivity.class);
if (!(context instanceof Activity)) {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
context.startActivity(intent);
}
}
CheckBox muttonCheckBox;
CheckBox chickenCheckBox;
CheckBox newCheckBox;
TextView logTextView;
Barbecue barbecue;
Waiter waiter;
MuttonCommand muttonCommand;
ChickenCommand chickenCommand;
NewCommand newCommand;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_command);
setTitle("命令模式");
muttonCheckBox = findViewById(R.id.checkBoxMutton);
chickenCheckBox = findViewById(R.id.checkBoxChicken);
newCheckBox = findViewById(R.id.checkBoxNew);
logTextView = findViewById(R.id.textViewLog);
barbecue = new Barbecue();
waiter = new Waiter();
muttonCommand = new MuttonCommand(barbecue);
chickenCommand = new ChickenCommand(barbecue);
newCommand = new NewCommand(barbecue);
}
public void onOrderClick(View view) {
if (muttonCheckBox.isChecked()) {
waiter.setOrder(muttonCommand);
}
if (chickenCheckBox.isChecked()) {
waiter.setOrder(chickenCommand);
}
if (newCheckBox.isChecked()) {
waiter.setOrder(newCommand);
}
logTextView.setText(waiter.show());
}
public void onCancelClick(View view) {
if (muttonCheckBox.isChecked()) {
waiter.cancelOrder(muttonCommand);
}
if (chickenCheckBox.isChecked()) {
waiter.cancelOrder(chickenCommand);
}
if (newCheckBox.isChecked()) {
waiter.cancelOrder(newCommand);
}
logTextView.setText(waiter.show());
}
public void onNoticeClick(View view) {
waiter.notice();
logTextView.setText(waiter.show());
waiter.reset();
}
public void onResetClick(View view) {
waiter.reset();
logTextView.setText(waiter.show());
}
}
Demo地址
https://gitee.com/zhangxusong888/Android/tree/master/design_pattern
网友评论