设计模式之命令模式

本文通过一个客户需求变更场景,详细介绍了命令模式的应用过程。从最初的直接调用到引入Invoker进行解耦,再到最终采用命令模式实现完全解耦并具备良好的扩展性。文章通过具体代码实现了这一过程,并总结了命令模式的优缺点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 命令模式的引入

1.1 有三个组分别为需求组、美工组、代码组,客户对开发的产品有些地方需要修改,修改对应的功能就要找到对应的组别。如下UML:

这里写图片描述

具体代码实现:

abstract class Group{

    //甲乙双方式分开办公,所以甲方需要通过find方法来找到对应的组
    public abstract void find();

    //增加一个功能
    public abstract void add();

    public abstract void delete();
}

class RequirementGroup extends Group{

    @Override
    public void find() {
        System.out.println("找到需求组。。。");
    }

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

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

}

class CodeGroup extends Group{

    @Override
    public void find() {
        System.out.println("客户找到代码组。。。");
    }

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

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

class PageGroup extends Group{

    public void find() {
        System.out.println("客户找到美工组...");
    }

    public void add() {
        System.out.println("客户要求新增一个页面...");
    }

    public void delete() {
        System.out.println("客户要求删除一个页面...");
    }

}

public class Client {
    public static void main(String[] args) {
        Group group = new RequirementGroup();
        group.find();
        group.add();
        group = new PageGroup();
        group.find();
        group.add();
        group = new CodeGroup();
        group.find();
        group.add();
    }
}

这样问题出现了,客户需要了解每个组的职能,然后根据自己需求找到具体的组别,而不是关注自己的命令是否被执行了。

1.2 我们对上述实现方式进行优化,增加一个Invoker 来屏蔽客户对组别的依赖。

UML

具体代码实现:

abstract class Group{

    //甲乙双方式分开办公,所以甲方需要通过find方法来找到对应的组
    public abstract void find();

    //增加一个功能
    public abstract void add();

    public abstract void delete();
}

class RequirementGroup extends Group{

    @Override
    public void find() {
        System.out.println("找到需求组。。。");
    }

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

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

}

class CodeGroup extends Group{

    @Override
    public void find() {
        System.out.println("客户找到代码组。。。");
    }

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

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

class PageGroup extends Group{

    public void find() {
        System.out.println("客户找到美工组...");
    }

    public void add() {
        System.out.println("客户要求新增一个页面...");
    }

    public void delete() {
        System.out.println("客户要求删除一个页面...");
    }

}

class Invoker{
    private String command;

    public Invoker(String command) {
        super();
        this.command = command;
    }

    public void execute(){
        if("addRequirement".equals(command)){
            Group group = new RequirementGroup();
            group.find();
            group.add();
        }else if("addPage".equals(command)){
            Group group = new PageGroup();
            group.find();
            group.add();
        }
    }
}


public class Client {
    public static void main(String[] args) {
        Invoker invoker = new Invoker("addRequirement");
        invoker.execute();
    }
}

这样优化后还是存在问题,一是字符串是没有约束力的,二是对于扩展不方便。为了把命令的接受者(Group)和命令发起者分离。使命令的发起者和命令(Command)关联,这样命令发起者只需要知道有什么命令就可以了。

这样我们就引入了命令模式

2. 命令模式

命令模式UML

  • 组别GroupCommand 抽象类中创建,初始化Invoker 时需要传入Command
  • 具体代码实现:
abstract class Group{

    //甲乙双方式分开办公,所以甲方需要通过find方法来找到对应的组
    public abstract void find();

    //增加一个功能
    public abstract void add();

    public abstract void delete();
}

class RequirementGroup extends Group{

    @Override
    public void find() {
        System.out.println("找到需求组。。。");
    }

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

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

}

class CodeGroup extends Group{

    @Override
    public void find() {
        System.out.println("客户找到代码组。。。");
    }

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

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

class PageGroup extends Group{

    public void find() {
        System.out.println("客户找到美工组...");
    }

    public void add() {
        System.out.println("客户要求新增一个页面...");
    }

    public void delete() {
        System.out.println("客户要求删除一个页面...");
    }

}

abstract class Command{
    protected Group codeGroup = new CodeGroup();
    protected Group pageGroup = new PageGroup();
    protected Group requirementGroup = new RequirementGroup();
    public abstract void execute();
}

class AddFunctionCommand extends Command{

    @Override
    public void execute() {
        super.codeGroup.find();
        super.codeGroup.add();
    }
}

class AddPageCommand extends Command{

    @Override
    public void execute() {
        super.pageGroup.find();
        super.pageGroup.add();
    }
}

class AddRequirementCommand extends Command{

    @Override
    public void execute() {
        super.requirementGroup.find();
        super.requirementGroup.add();
    }

}

class Invoker{
    private Command command;

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

public class Client {
    public static void main(String[] args) {
        Invoker invoker = new Invoker(new AddRequirementCommand());
        invoker.execute();
        invoker = new Invoker(new AddPageCommand());
        invoker.execute();
        invoker = new Invoker(new AddFunctionCommand());
        invoker.execute();
    }
}

运行结果:

找到需求组。。。
客户要求增加一项需求。。。
客户找到美工组…
客户要求新增一个页面…
客户找到代码组。。。
客户要求增加一项功能。。。

小结

命令模式的优点:

  1. 实现类之间的解耦(之前客户直接与各组相关联,优化后客户只与命令相关联)
  2. 具有可扩展型,扩展一个命令特别简单

缺点:

  1. 命令泛滥,N种组合命令
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值