通过<<大话设计模式>>这本书,开始认真学习设计模式,先学习了命令模式(Command).
命令模式(Command):将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作.
照着书里的例子写了一遍,书里的例子好像是C#版的,这里我修改成了Java版,初学者建议从紧耦合开始做,我就是这么做的,然后很快能明白,如果直接就写成命令模式比较难理解.
业务分析:顾客到烧烤店,顾客点单(烤肉,烤鸡翅),服务员记录并通知烧烤师傅进行烧烤,如果烤肉或烤鸡翅没有了,服务员要告知顾客;顾客点单后,可以选择撤销已经点过的.
package cn.pattern.command;
/**
* 负责烤肉串的人
* @author root
*/
public class PersonBarbecue {
/**
* 烤羊肉串
*/
public void bakeMutton(){
System.out.println("烤羊肉串");
}
/**
* 烤鸡翅
*/
public void bakeChickenWing(){
System.out.println("烤鸡翅");
}
}
package cn.pattern.command;
/**
* 抽象命令
* @author root
*
*/
public abstract class Command {
protected PersonBarbecue pb;
public Command() {
}
/**
* 确定执行命令的人,即烤肉串者是谁
* @param pb
*/
public Command(PersonBarbecue pb) {
this.pb = pb;
}
abstract public void excuteCommand();
}
package cn.pattern.command;
/**
* 烤鸡翅命令
* @author root
*
*/
public class BakeChickenWingCommand extends Command{
public BakeChickenWingCommand() {
}
public BakeChickenWingCommand(PersonBarbecue pb) {
super(pb);
}
@Override
public void excuteCommand() {
pb.bakeChickenWing();
}
}
package cn.pattern.command;
/**
* 烤肉命令
* @author root
*
*/
public class BakeMuttonCommand extends Command{
public BakeMuttonCommand() {
}
public BakeMuttonCommand(PersonBarbecue pb) {
// this.pb = pb;两种写法都行,但不写肯定不行!
super(pb);
}
@Override
public void excuteCommand() {
pb.bakeMutton();
}
}
package cn.pattern.command;
import java.util.LinkedList;
import java.util.List;
import cn.utils.ClassUtils;
/**
* 服务员类
* @author root
*
*/
public class PersonWaiter {
/**
* 存放顾客的订单(命令)
*/
private List<Command> commands = new LinkedList<Command>();
/**
* 不管用户想要什么烤肉,都是命令;服务员只管记录命令(订单),然后通知烤肉者执行即可
* @param command
*/
public void setOrder(Command command) {
//如果是烤鸡翅,向顾客说明鸡翅没有了,其它的加入订单
if((ClassUtils.getClassName(command)).equals("BakeChickenWingCommand")){
System.out.println("客户要求:"+ClassUtils.getClassName(command));
System.out.println("鸡翅没有了");
}else{
System.out.println("客户要求:"+ClassUtils.getClassName(command));
commands.add(command);
System.out.println("增加了一个订单:"+ClassUtils.getClassName(command));
}
}
/**
* 取消订单
*/
public void cancelCommand(Command command){
commands.remove(command);
System.out.println("取消订单:"+command.getClass().getName());
}
/**
* 通知执行烤肉者
*/
public void advise(){
for(Command command:commands){
command.excuteCommand();
}
}
}
package cn.pattern.command;
public class Client {
public static void main(String[] args) {
//开店前准备工作,要有烤肉者,顾客可能点到的订单,服务员
PersonBarbecue pb = new PersonBarbecue();
PersonWaiter pw = new PersonWaiter();
Command c1 = new BakeMuttonCommand(pb);
Command c3 = new BakeMuttonCommand(pb);
Command c2 = new BakeChickenWingCommand(pb);
//开门营业
pw.setOrder(c1);//客人要烤肉串
pw.setOrder(c2);//客人要烤鸡翅
pw.setOrder(c3);//客人要烤鸡翅
pw.advise();
}
}
为了能获取不带包路径的类名,写了个工具package cn.utils;
public class ClassUtils {
/**
* 根据包机构的类名,返回不带包机构的类名
*
* @param classPackageName
* @return
*/
public static String getClassName(String classPackageName) {
int lastIndexOf = classPackageName.lastIndexOf(".");
return classPackageName.substring(lastIndexOf + 1);
}
/**
* 根据对象,返回不带包机构的类名
*
* @param object
* @return
*/
public static String getClassName(Object object) {
String classPackageName = object.getClass().getName();
int lastIndexOf = classPackageName.lastIndexOf(".");
return classPackageName.substring(lastIndexOf + 1);
}
}