某天接到客户的需求,我们的项目需要增加新需求,项目经理找到需求组同事说我们需要增加一条需求,然后找到UI设计组同事说我们需要增加一条需求做好ui设计,然后跑到代码组同事说我们要增加一条需求赶紧准备撸代码,最后跑到测试组同事说我们要增加一条需求赶紧写好测试用例。我们现在来用代码实现这个过程。
抽象组:
public abstract class Group
{
//找到改组的人
public abstract void find();
//增加一条需求
public abstract void add();
//删除一条需求
public abstract void delete();
}
需求组:
public class RequirementGroup extends Group
{
@Override
public void find()
{
// TODO Auto-generated method stub
System.out.println("找到需求组");
}
@Override
public void add()
{
// TODO Auto-generated method stub
System.out.println("增加一条需求");
}
@Override
public void delete()
{
// TODO Auto-generated method stub
System.out.println("删除一条需求");
}
UI设计组:
public class UIDesignGroup extends Group
{
@Override
public void find()
{
// TODO Auto-generated method stub
System.out.println("找到ui设计组");
}
@Override
public void add()
{
// TODO Auto-generated method stub
System.out.println("增加一条需求");
}
@Override
public void delete()
{
// TODO Auto-generated method stub
System.out.println("删除一条需求");
}
}
代码组:
public class CodeGroup extends Group
{
@Override
public void find()
{
// TODO Auto-generated method stub
System.out.println("找到代码组");
}
@Override
public void add()
{
// TODO Auto-generated method stub
System.out.println("增加一条需求");
}
@Override
public void delete()
{
// TODO Auto-generated method stub
System.out.println("删除一条需求");
}
}
测试组:
public class TestGroup extends Group
{
@Override
public void find()
{
// TODO Auto-generated method stub
System.out.println("找到测试组");
}
@Override
public void add()
{
// TODO Auto-generated method stub
System.out.println("增加一条需求");
}
@Override
public void delete()
{
// TODO Auto-generated method stub
System.out.println("删除一条需求");
}
}
场景类:
public class Client
{
public static void main(String[] args)
{
System.out.println("========找到需求组,增加需求=====");
RequirementGroup requirementGroup = new RequirementGroup();
requirementGroup.find();
requirementGroup.add();
System.out.println("========找到UI设计组,增加需求=====");
UIDesignGroup uiDesignGroup = new UIDesignGroup();
uiDesignGroup.find();
uiDesignGroup.add();
System.out.println("========找到代码组,增加需求=====");
CodeGroup codeGroup = new CodeGroup();
codeGroup.find();
codeGroup.add();
System.out.println("========找到测试组,增加需求=====");
TestGroup testGroup = new TestGroup();
testGroup.find();
testGroup.add();
System.out.println("========终于增加需求成功=====");
}
}
执行结果:
========找到需求组,增加需求=====
找到需求组
增加一条需求
========找到UI设计组,增加需求=====
找到ui设计组
增加一条需求
========找到代码组,增加需求=====
找到代码组
增加一条需求
========找到测试组,增加需求=====
找到测试组
增加一条需求
========终于增加需求成功=====
代码写完了,会发现问题,假如这个项目经理叫你当,你会担任吗?肯定不会,当客户需求不断变化时项目经理都会累死,工作效率低下,各部门同事会嫌弃死你,肯定不会去背这锅。下面对我们的代码进行修改让你能胜任这个项目经理职位。
把增加/删除需求的操作封装成命令:
抽象命令:
public abstract class Command
{
RequirementGroup requirementGroup = new RequirementGroup();
UIDesignGroup uiDesignGroup = new UIDesignGroup();
CodeGroup codeGroup = new CodeGroup();
TestGroup testGroup = new TestGroup();
public abstract void execute();
}
增加需求命令:
public class AddRequirementCommand extends Command
{
@Override
public void execute()
{
// TODO Auto-generated method stub
super.requirementGroup.find();
super.requirementGroup.add();
super.uiDesignGroup.find();
super.uiDesignGroup.add();
super.codeGroup.find();
super.codeGroup.add();
super.testGroup.find();
super.testGroup.add();
}
}
删除需求命令:
public class DeleteRequirementCommand extends Command
{
@Override
public void execute()
{
// TODO Auto-generated method stub
super.requirementGroup.find();
super.requirementGroup.delete();
super.uiDesignGroup.find();
super.uiDesignGroup.delete();
super.codeGroup.find();
super.codeGroup.delete();
super.testGroup.find();
super.testGroup.delete();
}
}
项目经理:
public class Invoker
{
private Command command;
public Command getCommand()
{
return command;
}
public void setCommand(Command command)
{
this.command = command;
}
public void action()
{
this.command.execute();
}
}
各组(需求组,ui设计组,代码组,测试组)的代码不变,不在重写。
场景类:
public class Client1
{
public static void main(String[] args)
{
Invoker invoker = new Invoker();
Command addCommand = new AddRequirementCommand();
Command deleteCommand = new DeleteRequirementCommand();
invoker.setCommand(addCommand);
invoker.action();
invoker.setCommand(deleteCommand);
invoker.action();
}
}
执行结果:
找到需求组
增加一条需求
找到ui设计组
增加一条需求
找到代码组
增加一条需求
找到测试组
增加一条需求
找到需求组
删除一条需求
找到ui设计组
删除一条需求
找到代码组
删除一条需求
找到测试组
删除一条需求
改装后的代码可以发现项目经理只需要接收客户发送命令(增加/删除需求),然后执行自己的action()方法就可以完成需求的增加和删除,实现的过程不需要项目经理去参与,这样的项目经理相信你能胜任。这就是命令模式。
命令模式定义
命令模式:Encapsulate a request as an object,thereby letting you parameterize clients with different requests,queue or log requests,and support undoable operations.(将一个请求对象封装成一个对象,从而让你使用不同的请求把客户端参数化,把请求排队或者记录请求日志,可以提供命令的撤销和 恢复功能。)
命令模式角色
Receive接受者角色:具体的干活角色,命令传送到这里就要执行,对应上述例子的各个group,可以把receive抽象化,然后接受不同的命令。
Command命令角色:需要执行的所有命令都在这里执行。
Invoke调用者角色:接收到命令,执行命令。比如例子中的项目经理。
命令模式的优点
类间解耦:调用者角色与接收者角色直接没有任何依赖关系。
可扩展性:Command的子类可以很容易的扩展。
命令模式结合其他模式会更优秀:结合模板方法模式可以减少Command子类的膨胀问题。
命令模式的缺点
Command子类不断膨胀。