策略模式和命令模式的PK

策略模式它的意图是封装算法,它认为算法是一个整体,是相互独立的,并且是可以相互替换的,让算法的行为独立于客户。

命令模式它的意图是解耦,它让执行命令者和发布命令者分离。

实现一个压缩和解压缩的功能,这个功能有两种算法:一种是gzip,一种是zip。

1. 策略模式的实现:

策略模式

代码:

interface Algorithm{

    public void zipExecute();

    public void gzipExecute();

}

class CompressAlgorithm implements Algorithm{

    public void zipExecute() {
        System.out.println("zip压缩成功!");
    }

    public void gzipExecute() {
        System.out.println("gzip压缩成功");
    }
}

class UnCompressedAlgorithm implements Algorithm{

    public void zipExecute() {
        System.out.println("Zip解压成功!");
    }

    public void gzipExecute() {
        System.out.println("gzip解压成功!");
    }

}

class Context{
    private Algorithm algorithm;

    public Context(Algorithm algorithm) {
        super();
        this.algorithm = algorithm;
    }

    public void zipExecute(){
        algorithm.zipExecute();
    }

    public void gzipExecute(){
        algorithm.gzipExecute();
    }
}

public class Client {
    public static void main(String[] args) {
        Context context = new Context(new CompressAlgorithm());
        context.gzipExecute();
        context.zipExecute();
        context = new Context(new UnCompressedAlgorithm());
        context.gzipExecute();
        context.zipExecute();
    }
}

策略模式中,虽然有两个算法,一个是zip另外一个是Gzip,但是对于调用者来说,这两个算法没有本质区别,只是“形式”不一样而已。对于Client来说,我用哪个算法都无所谓,关键是能帮忙压缩和解压就可以了。

2. 命令模式:

命令模式

我们把上面的模型比作去餐馆点菜,客人(Client)是请求者,通过服务员(Invoker)向厨师(Receiver)发送点菜请求(Command)。命令对应具体接受者,也就是哪一道菜对应哪个厨师。命令模式的意图在于解耦,即,客人不和厨师直接打交道。

interface IReceiver{
    public void zipExecute();
    public void gzipExecute();
}

class CompressReceiver implements IReceiver{

    @Override
    public void zipExecute() {
        System.out.println("Zip压缩成功");
    }

    @Override
    public void gzipExecute() {
        System.out.println("Gzip压缩成功");
    }
}

class UnCompressReceiver implements IReceiver{

    @Override
    public void zipExecute() {
        System.out.println("Zip解压成功");
    }

    @Override
    public void gzipExecute() {
        System.out.println("GZip解压成功");
    }
}

abstract class Command{
    protected IReceiver compressReceiver = new CompressReceiver();

    protected IReceiver unCompressReceiver = new UnCompressReceiver();

    public abstract void execute();
}

class GZipCompressCommand extends Command{

    @Override
    public void execute() {
        super.compressReceiver.gzipExecute();
    }
}

class GZipUnCompressCommand extends Command{

    @Override
    public void execute() {
        super.unCompressReceiver.gzipExecute();
    }
}

class ZipCompressCommand extends Command{

    @Override
    public void execute() {
        super.compressReceiver.zipExecute();
    }

}

class ZipUnCompressCommand extends Command{

    @Override
    public void execute() {
        super.unCompressReceiver.zipExecute();
    }

}


class Invoker{
    private Command command;

    public void setCommand(Command command) {
        this.command = command;
    }

    public void deliverCommand(){
        this.command.execute();
    }
}

public class Client {
    public static void main(String[] args) {
        Invoker invoker = new Invoker();
        invoker.setCommand(new ZipCompressCommand());
        invoker.deliverCommand();
    }
}

3. 改造接口

3.1 为了体现命令模式的解耦意图,我们对接口IReceiver进行改造,按职责来划分,如下:

interface IReceiver{
    public void compress();
    public void uncompress();
}

class ZipReceiver implements IReceiver{

    @Override
    public void compress() {
        System.out.println("Zip压缩成功");
    }

    @Override
    public void uncompress() {
        System.out.println("Zip解压成功");
    }
}

class GzipReceiver implements IReceiver{

    @Override
    public void compress() {
        System.out.println("Gzip压缩成功");
    }

    @Override
    public void uncompress() {
        System.out.println("Gzip解压成功");
    }
}

abstract class Command{
    protected IReceiver zipReceiver = new ZipReceiver();

    protected IReceiver gzipReceiver = new GzipReceiver();

    public abstract void execte();
}

class ZipCompressCommand extends Command{

    @Override
    public void execte() {
        super.zipReceiver.compress();
    }
}

class ZipUnCompressCommand extends Command{

    @Override
    public void execte() {
        super.zipReceiver.uncompress();
    }
}

class GZipCompressCommand extends Command{

    @Override
    public void execte() {
        super.gzipReceiver.compress();
    }

}

class GZipUnCompressCommand extends Command{

    @Override
    public void execte() {
        super.gzipReceiver.uncompress();
    }

}

class Invoker{
    private Command command;

    public void setCommand(Command command) {
        this.command = command;
    }

    public void deliverCommand(){
        this.command.execte();
    }
}

public class Client {
    public static void main(String[] args) {
        Invoker invoker = new Invoker();
        invoker.setCommand(new ZipCompressCommand());
        invoker.deliverCommand();
    }
}

我们发现无论底层命令实现怎么修改,客户都都不需要发生变化,这就体现了命令模式的解耦的意图。

3.2 而反观策略模式,如果要按职责进行修改的话,就要修改它的抽象算法:

interface Algorithm{

    public void compress();

    public void uncompress();

}

class Zip implements Algorithm{

    @Override
    public void compress() {
        System.out.println("zip压缩成功");
    }

    @Override
    public void uncompress() {
        System.out.println("zip解压成功");
    }
}

class GZip implements Algorithm{

    @Override
    public void compress() {
        System.out.println("Gzip压缩成功");
    }

    @Override
    public void uncompress() {
        System.out.println("Gzip解压成功");
    }

}

class Context{
    private Algorithm algorithm;

    public Context(Algorithm algorithm) {
        super();
        this.algorithm = algorithm;
    }

    public void compress(){
        algorithm.compress();
    }
    public void uncompress(){
        algorithm.uncompress();
    }
}

public class Client {
    public static void main(String[] args) {
        Context context = new Context(new GZip());
        context.compress();
        context = new Context(new Zip());
        context.compress();
    }
}

策略模式的初衷就是封装算法,而我们这样做就打破了策略模式对算法的封装,违背了它的初衷。

而命令模式却可以随意对接口进行修改,按职责来划分,是因为命令模式着重于请求者和接受者的解耦,只要不影响请求者就行了。这才是命令模式的意图。

小结:

  1. 两种模式的关注点不同,策略模式关注的是算法的完整性和封装性,只要具备了这两个条件才能保证其可切换。
  2. 职责,比如菜单栏里有”复制”,“剪切”等,命令模式对应的是“复制”,“剪切”等各个功能,而策略模式对应的是“复制”这一个功能,但是“复制”有各种形式,我们可以用鼠标点击复制,也可以用快捷键。但无论怎么样,都是在做同一样事情,那就是复制。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值