暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

20.设计模式--命令模式(Command模式)

大猫的Java笔记 2021-11-17
202
1.定义





  命令模式是一种行为型模式,将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作。



  作为开发人员经常会接到需求,然后根据需求进行代码编写,当然需求一般都是先产品做好原型图,UI再设计,然后前端后端开发,最后通过测试进行测试。如果这一天需求发生了变化,也就是所谓的命令。让ui改变一下图。或者让开发人员增加一个新功能。那么有了下面这样的操作。



  Group是对不同人员的抽象,他们的子类包含了产品经理、ui以及开发人员。



public abstract class Group {


//甲乙双方分开办公,你要和那个组讨论,你首先要找到这个组
public abstract void find();


//被要求增加功能
public abstract void add();


//被要求删除功能
public abstract void delete();


//被要求修改功能
public abstract void change();


//被要求给出所有的变更计划
public abstract void plan();
}
复制



  ProductManagerGroup、UiGroup、CodeGroup分别表示产品组、UI组以及开发组



public class ProductManagerGroup extends Group{




//客户要求需求组过去和他们谈
@Override
public void find() {
System.out.println("找到需求组...");
}


//客户要求增加一项需求
@Override
public void add() {
System.out.println("客户要求增加一项需求...");
}


@Override
//客户要求修改一项需求
public void change() {
System.out.println("客户要求修改一项需求...");
}


//客户要求删除一项需求
@Override
public void delete() {
System.out.println("客户要求删除一项需求...");
}


//客户要求出变更计划
@Override
public void plan() {
System.out.println("客户要求需求变更计划...");
}
}
复制


public class UiGroup extends Group{


//客户要求需求组过去和他们谈
@Override
public void find() {
System.out.println("找到美工组...");
}


//客户要求增加一项需求
@Override
public void add() {
System.out.println("客户要求增加一项需求...");
}


@Override
//客户要求修改一项需求
public void change() {
System.out.println("客户要求修改一项需求...");
}


//客户要求删除一项需求
@Override
public void delete() {
System.out.println("客户要求删除一项需求...");
}


//客户要求出变更计划
@Override
public void plan() {
System.out.println("客户要求需求变更计划...");
}
}
复制


public class CodeGroup extends Group{


//客户要求需求组过去和他们谈
@Override
public void find() {
System.out.println("找到开发组...");
}


//客户要求增加一项需求
@Override
public void add() {
System.out.println("客户要求增加一项需求...");
}


@Override
//客户要求修改一项需求
public void change() {
System.out.println("客户要求修改一项需求...");
}


//客户要求删除一项需求
@Override
public void delete() {
System.out.println("客户要求删除一项需求...");
}


//客户要求出变更计划
@Override
public void plan() {
System.out.println("客户要求需求变更计划...");
}
}
复制



  此时如果要找产品改需求,就可以如下所示,先找到产品,然后增加功能,最后进行需求变更。



public class Test {


public static void main(String[] args) {
Group productManagerGroup = new ProductManagerGroup();
productManagerGroup.find();
productManagerGroup.add();
productManagerGroup.plan();
}
}
复制


找到需求组...
客户要求增加一项需求...
客户要求需求变更计划...
复制



  如果需要找开发人员增加功能,那么同样也是先找到开发,然后增加功能,最后需求变更。



public class Test {


public static void main(String[] args) {
Group codeGroup = new CodeGroup();
codeGroup.find();
codeGroup.add();
codeGroup.plan();
}
}
复制


找到开发组...
客户要求增加一项需求...
客户要求需求变更计划...
复制


  现在如果又要找UI更改图,是不是有需要先找到UI组,然后进行对应的操作,可是这样需求一直变来去的,如果说找的是产品经理改了对应需求,而开发人员不知道啊,那么是不是可能最后实际的效果和客户要的不一致,因为产品没给开发同步。

  而且对于客户来说我每次改需求难道所有的组都要通知吗?能不能给我来一个对接的人,我的需求改动也就是命令,只是告诉和我同步的人,然后同步的人告诉所有的开发人员。如果中间加了一个中间人这样也让客户和对应的开发人员做了解耦。



2.命令模式实现



  基于开发人员以及产品、美工的要求,我们加一个中间人,不然客户永远在随便单独叫人去改,改了也不给大家同步。



  Command就是命令,对于客户提出的命令总要有人执行吧,所以在Command中引用了产品组、美工组以及代码组,毕竟命令来了要知道谁去做,而execute就是做事情的抽象,至于谁做,怎么做是子类应该决定的事情



public abstract class Command {


//把三个组都定义好,子类可以直接使用
    //产品组
protected ProductManagerGroup pmg = new ProductManagerGroup();


//美工组
protected UiGroup ug = new UiGroup();


//代码组;
protected CodeGroup cg = new CodeGroup();


//只要一个方法,你要我做什么事情
public abstract void execute();
}
复制



  Invoker就是中间人,客户只需要给中间人说我要改什么东西,至于究竟改谁,都是中间人来决定,如果需要产品的原型图、ui的设计图、前端后端的代码都改动,那也是中间人来决定。



public class Invoker {


private Command command;


public Invoker(Command command) {
this.command = command;
}


//执行客户的命令
public void action(){
this.command.execute();
}
}


复制



  而对于AddRequirementCommand、ChangeRequirementCommand以及DeleteRequirementCommand都是一个命令,对需求改动的命令,至于让谁做是他们来决定的,我可以让产品、美工、开发都改动,也可以只让其中一个组做改动。现在如果要改动一个需求是不是可以通知到对应的组了,同时调用者和开发者做到了解耦。



public class AddRequirementCommand extends Command{
@Override
public void execute() {
super.pmg.find();
super.pmg.add();
super.pmg.plan();
}
}
复制


public class ChangeRequirementCommand extends Command{
@Override
public void execute() {
super.pmg.find();
super.pmg.change();
super.pmg.plan();
}
}
复制


public class DeleteRequirementCommand extends Command{
@Override
public void execute() {
super.pmg.find();
super.pmg.delete();
super.pmg.plan();
}
}


复制



  现在对于客户来说只需要去找中间人,不在需要去一个一个的去找是那个组做,同时还避免了可能涉及到通知不到的组。



public class Test {
public static void main(String[] args) {
Invoker invoker = new Invoker(new AddRequirementCommand());
invoker.action();
}
}
复制


找到需求组...
客户要求增加一项需求...
客户要求需求变更计划...
复制


命令模式中的角色


  Receiver角色:这个就是干活的角色,命令传递到这里是应该被执行的,具体到上面我们的例子中就是 Group 的三个实现类; 

  Command角色:就是命令,需要我执行的所有命令都这里声明;例子中就是对应的AddRequirementCommand、ChangeRequirementCommand以及DeleteRequirementCommand。

  Invoker角色:调用者,接收到命令,并执行命令,例子中就是Invker类。



参考文献《设计式之禅

代码获取地址:https://gitee.com/bughong/design-pattern




文章转载自大猫的Java笔记,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论