一、项目经理也难当
1. 抽象组
public abstract class Group {
//甲乙双方分开办公,如果你要和某个级讨论,你首先要找到这个组
public abstract void find();
//被要求增加功能
public abstract void add();
//被要求删除功能
public abstract void delete();
//被要求修改功能
public abstract void change();
//被要求给出所有的变更计划
public abstract void plan();
}
2. 需求组
public class RequirementGroup extends Group{
//客户需要需求组过去和他们谈
public void find() {
System.out.println("找到需求组");
}
//客户要求增加一项需求
public void add() {
System.out.println("客户要求增加一项需要");
}
//客户要求修改一项需求
public void delete() {
System.out.println("客户要求修改一项需求");
}
//客户要求删除一项需求
public void change() {
System.out.println("客户要求删除一项需求");
}
//客户要求给出变更计划
public void plan() {
System.out.println("客户要求需要变更计划");
}
}
3. 美工组
public class PageGroup extends Group{
//首先这个美工组应该能找到吧,
public void find() {
System.out.println("找到美工组");
}
//美工被要求增加一个页面
public void add() {
System.out.println("客户要求增加一个页面");
}
//客户要求对现有界面做修改
public void delete() {
System.out.println("客户要求修改一个页面");
}
//甲方是老大,要求删除一些页面
public void change() {
System.out.println("客户要求删除一个页面");
}
//所有的增删改都要给出计划
public void plan() {
System.out.println("客户要求页面变更计划");
}
}
4. 代码组
public class CodeGroup extends Group{
//客户要求代码组过去和他们谈
public void find() {
System.out.println("找到代码组...");
}
//客户要求增加一项功能
public void add() {
System.out.println("客户要求增加一项功能");
}
//客户要求修改一项功能
public void delete() {
System.out.println("客户要求修改一项功能");
}
//客户要求删除一项功能
public void change() {
System.out.println("客户要求删除一项功能");
}
//客户要求给出变更计划
public void plan() {
System.out.println("客户要求代码变更计划...");
}
}
5. 抽象命令类
public abstract class Command {
//把三个组都定义好,子类可以直接使用
protected RequirementGroup rg = new RequirementGroup();//需求组
protected PageGroup pg = new PageGroup();//美工组
protected CodeGroup cg = new CodeGroup();//代码组
//只有一个方法,你要我做什么事情
public abstract void execute();
}
6. 增加需求的命令
public class AddRequirementCommand extends Command{
//执行增加一项需求的命令
public void execute() {
//找到需求组
super.rg.find();
//增加一份需求
super.rg.add();
//给出计划
super.rg.plan();
}
}
7. 删除页面的命令
public class DeletePageCommand extends Command{
//执行删除一个页面的命令
public void execute() {
//找到页面组
super.pg.find();
//删除一个页面
super.pg.delete();
//给出计划
super.pg.plan();
}
}
8. 负责人(负责人说,有什么命令new出来通过action传给我,我去给下面人说execute)
public class Invoker {
//什么命令
private Command command;
//客户发出命令
public void setCommand(Command command) {
this.command = command;
}
//执行客户的命令
public void action(){
this.command.execute();
}
}
9. 场景类
public class Client {
public static void main(String[] args) {
//定义我们的接头人
Invoker xiaoSan = new Invoker();
//客户要求增加一项需求
System.out.println("---------客户需求增加一项需求------------");
//客户给我们下命令来
Command command = new AddRequirementCommand();
//接头人接收到命令
xiaoSan.setCommand(command);
xiaoSan.action();
System.out.println("--------客户要求删除一个页面-------------");
//客户给我们下命令来
Command command2 = new DeletePageCommand();
xiaoSan.setCommand(command2);
xiaoSan.action();
}
}
二、命令模式的定义
1. 通用Receiver类
public abstract class Receiver {
//抽象定义者,定义每个接收者都必须完成的业务
public abstract void doSomething();
}
2. 具体的Receiver类
public class ConcreteReciver1 extends Receiver{
//每个接收者都必须处理一定的业务逻辑
public void doSomething() {
System.out.println("doSomething1");
}
}
&
public class ConcreteReciver2 extends Receiver{
//每个接收者都必须处理一定的业务逻辑
public void doSomething() {
System.out.println("doSomething2");
}
}
3. 抽象的Command命令类
public abstract class Command {
//每个命令类都必须有一个执行命令的方法
public abstract void execute();
}
4. 具体的Command命令类
public class ConcreteCommand1 extends Command{
//对哪个Receiver类进行命令处理
private Receiver receiver;
//构造函数传递接收者
public ConcreteCommand1(Receiver receiver) {
this.receiver = receiver;
}
//必须实现一个命令
public void execute() {
//业务处理
this.receiver.doSomething();
}
}
&
public class ConcreteCommand2 extends Command{
//哪个Receiver类进行命令处理
private Receiver receiver;
//构造函数传递接收者
public ConcreteCommand2(Receiver receiver) {
this.receiver = receiver;
}
//必须实现一个命令
public void execute() {
//业务处理
this.receiver.doSomething();
}
}
5. 调用者invoker类
public class Invoker {
private Command command;
//受气包,接受命令
public void setCommand(Command command) {
this.command = command;
}
//执行命令
public void action(){
this.command.execute();
}
}
6. 场景类
public class Client {
public static void main(String[] args) {
//首先声明调用者Invoker
Invoker invoker = new Invoker();
//定义接收者
Receiver receiver = new ConcreteReciver1();
//定义一个发送给接收者的命令
Command command = new ConcreteCommand1(receiver);
//把命令交给调用者去执行
invoker.setCommand(command);
invoker.action();
}
}
三、命令模式的应用
1. 优点
类间解耦:调用者角色与接收者角色之间没有任何依赖关系,调用者实现功能时只要调用Command抽象类的execute方法就可以,不需要了解到底是哪个接收者执行。
可扩展性:Command的子类可以非常容易的扩展,而调用者Invoker和高层次的模块Client不产生严重的代码耦合。
可与其他模式结合:命令模式可以结合责任链模式,实现命令族解析任务,结合模板方法模式,则可以减少Command子类的膨胀问题
2. 缺点
如果有N个命令,就会有N个Command实现方法,就会很庞大。
3. 使用场景
只要你认为是命令的地方就可以采用命令模式,例如,GUI开发中,一个按钮的点击是一个命令,可以采用命令模式;模拟DOS命令时候,也可以采用命令模式;触发-反馈机制的处理等。
四、命令模式的扩展
1. 在一个命令中同时使用另一个命令
修改后的命令实现类AddRequirementCommand
public class AddRequirementCommand extends Command{
//执行增加一项需求的命令
public void execute() {
//找到需求组
super.rg.find();
//增加一份需求
super.rg.add();
//页面也要增加
super.pg.add();
//功能也要增加
super.cg.add();
//给出计划
super.rg.plan();
}
}
2. 撤销命令
修改后的Group类
public abstract class Group {
//甲乙双方分开办公,如果你要和某个级讨论,你首先要找到这个组
public abstract void find();
//被要求增加功能
public abstract void add();
//被要求删除功能
public abstract void delete();
//被要求修改功能
public abstract void change();
//被要求给出所有的变更计划
public abstract void plan();
//每个接收者都要对直接执行的任务可以回滚
public void rollBack(){
//根据日志进行回滚
}
}
撤销命令
public class CancelDeletePageCommand extends Command{
//撤销删除一个页面的命令
public void execute() {
super.pg.rollBack();
}
}
只是增加了一个Command命令类的实现类,为撤消类命令,但真实执行起来很困难,涉及到事务日志处理。
五、最佳实践
1. 完美的Command类
public abstract class Command {
//定义一个子类的全局共享变量
protected final Receiver receiver;
//实现类必须定义一个接收者
public Command(Receiver receiver) {
this.receiver = receiver;
}
//每个命令类都必须有一个执行命令的方法
public abstract void execute();
}
2. 具体的命令
public class ConcreteCommand1 extends Command{
//声明自己的默认接收者
public ConcreteCommand1(){
super(new ConcreteReciver1());
}
//设置新的接收者
public ConcreteCommand1(Receiver receiver) {
super(receiver);
}
//每个具体的命令都必须实现一个命令
public void execute(){
//业务处理
super.receiver.doSomething();
}
}
&
public class ConcreteCommand2 extends Command{
//声明自己的默认接收者
public ConcreteCommand2(){
super(new ConcreteReciver2());
}
//设置新的接收者
public ConcreteCommand2(Receiver receiver) {
super(receiver);
}
//每个具体的命令都必须实现一个命令
public void execute(){
//业务处理
super.receiver.doSomething();
}
}
3. 场景类
public class Client {
public static void main(String[] args) {
//首先声明调用者Invoker
Invoker invoker = new Invoker();
//定义一个发送给接收者的命令
Command command = new ConcreteCommand1();
//把命令交给调用者去执行
invoker.setCommand(command);
invoker.action();
}
}
这里高层次模块不需要知道接收者