学习策略模式过程中的一些问题

56 阅读6分钟

 不渴望能够一跃千里,只希望每天能够前进一步。

光阴易逝,岂容我待。

最近学习了下设计模式,发现了一些问题,记录下来。

目录

1、工厂模式和策略模式有什么区别?

2、策略模式真的能省略if和else判断吗?

3、策略模式是否有必要写个上下文类()Context?


在总结上面三个问题回答之前,我们先来写一遍策略模式。

网上的策略模式有多种写法,这里只举栗2种:

首先是没用设计模式之前的代码:

public Result calcPrice(int customerType){
    //判断客户类型执行不同计算价格方法
    if(customerType == 1){
        //计算白银客户优惠价..
    }else if(customerType == 2){
        //计算黄金客户优惠价..
    }else if(customerType == 3){
        //计算钻石客户优惠价..
    }
    .....
    else{
        //计算xx客户优惠价..
    }
}

策略模式第一种写法:

在客户端根据传入的策略类来判断

//价格策略接口
public interface IPriceStrategy{
    Result calcPrice();
}

//白银客户价格策略类
public class SilverPriceStrategy implements IPriceStrategy{
    Result calcPrice(){
        //计算白银客户优惠价..
    }
}

//黄金客户价格策略类
public class GoldPriceStrategy implements IPriceStrategy{
    Result calcPrice(){
        //计算黄金客户优惠价..
    }
}

//钻石客户价格策略类
public class DiamondPriceStrategy implements IPriceStrategy{
    Result calcPrice(){
        //计算钻石客户优惠价..
    }
}
...

//价格策略上下文类
public class CustomerPriceContext{
    private IPriceStrategy iPriceStrategy;
    
    public CustomerPriceContext(IPriceStrategy iPriceStrategy){
        this.iPriceStrategy = iPriceStrategy;
    }

    public Result calcPrice(){
        return this.iPriceStrategy.calcPrice();
    }
}

===========================================================================
//客户端调用
public Result calcPrice(){
    //计算白银客户优惠价..
    CustomerPriceContext context = new CustomerPriceContext(new SilverPriceStrategy());
    Result result = context.calcPrice();
    //计算黄金客户优惠价..
    CustomerPriceContext context = new CustomerPriceContext(new GoldPriceStrategy());
    Result result = context.calcPrice();
    //计算钻石客户优惠价..
    CustomerPriceContext context = new CustomerPriceContext(new DiamondPriceStrategy());
    Result result = context.calcPrice();
    ...
    //计算xx客户优惠价..    
    CustomerPriceContext context = new CustomerPriceContext(new XXPriceStrategy());
    Result result = context.calcPrice();

}

写完后,嗯,大家是不是感觉有点怪怪的

没错,我也觉得怪怪的。

我在网络上浏览了很多讲策略模式的帖子,他们都是用上面的写法作为例子,然后结束总结策略模式优点的时候提到:策略模式可以省略掉if else,让你的代码更加优雅

优雅个鬼啊!

在客户端不还是要写if else来判断new哪个策略方法吗?只是他们例子没有写出来,这样自欺欺人???

那策略模式可以省略if else吗?可以!不过写法是下面第二种写法:

在客户端传入客户类型字符串判断

//价格策略接口
public interface IPriceStrategy{
    Result calcPrice();
}

//白银客户价格策略类
public class SilverPriceStrategy implements IPriceStrategy{
    Result calcPrice(){
        //计算白银客户优惠价..
    }
}

//黄金客户价格策略类
public class GoldPriceStrategy implements IPriceStrategy{
    Result calcPrice(){
        //计算黄金客户优惠价..
    }
}

//钻石客户价格策略类
public class DiamondPriceStrategy implements IPriceStrategy{
    Result calcPrice(){
        //计算钻石客户优惠价..
    }
}
...

//价格策略上下文类
public class CustomerPriceContext{
    //通过hashmap来将判断条件与处理函数做个映射
    private final static HashMap<String,IPriceStrategy> strategyMap = new HashMap<>();
    
    static{
        strategyMap.put("silver",new SilverPriceStrategy());
        strategyMap.put("gold",new GoldPriceStrategy());
        strategyMap.put("diamond",new DiamondPriceStrategy());
        ...
        strategyMap.put("xx",new CStrategy());
    }

    private String customerType;

    public CustomerPriceContext(String customerType){
        this.customerType = customerType;
    }

    public Result calcPrice(){
        return this.strategyMap.get(this.customerType).calcPrice();
    }
}

===========================================================================
//客户端调用
public Result calcPrice(int customerType){
    String customerTypeDesc = getCustomerTypeDesc(customerType);
    CustomerPriceContext context = new CustomerPriceContext(customerType);
    Result result = context.calcPrice();
}

这第二种策略模式写法是利用的hashmap来取消if else的,所以我们这第二个问题:策略模式真的能省略if else 判断吗?我想你心中应该有了答案。

对比一、二两种方式,看你们喜欢用哪种咯。

反正我个人是更喜欢第二种方式哈哈哈哈。

因为第一种写法还是要写if else,这样在以后有新的客户类型加入后,你需要修改客户端类,在客户端新增if else,这并没有完全解耦合,另外万一有多处地方都调用了呢,那只能一个一个改咯。

而第二种写法不需要写if else了,他让客户端和计算价格模块完全解耦合,以后新增了客户类型不需要修改客户端的代码,仅仅修改这个价格策略模块的代码即可。

好了,看到这里,肯定有人发现了,这策略模式怎么和工厂模式这么像?请往下看

1、工厂模式和策略模式有什么区别?

嗯,还是先说说我在网上浏览帖子的情况,大家都说:

​编辑 

是不是看的头大?反正我是

我觉得吧,上面写的第一种策略模式和简单工厂模式差不多

上面写的第二种策略模式和工厂模式差不多

差异在哪呢?

代码差异: 工厂模式用的是factory命名。。。策略模式是用的Context上下文类。。老实讲我觉得差别不大,也就换换变量名加几个属性。

使用目的差异: 工厂模式当然是为了生产对象,只生产对象。而策略模式不是,策略模式是根据你传的参数来选择执行策略。他们直接的差别就是:工厂模式要生产一个给别人用的对象,策略模式要执行某段封装好的逻辑,可能有返回也可能没返回。

设计模式类型差异: 一个是创建型设计模式、一个是行为型设计模式。

阅读代码的时候的差异: 当我看到factory这个单词的时候,便能知道以后想获得个对象的时候,可以调用他的方法,当我看到strategy或者context这两单词的时候,我能联想到策略模式,要修改策略逻辑时能快速定位到需要修改的地方,而且修改范围不会大。

看完的大佬轻喷 -_-

2、策略模式真的能省略if和else判断吗?

不能,看上面的两种策略模式方式就能明白,省略if else的功劳hashmap更大一点。

3、策略模式是否有必要写个上下文类()Context?

有必要。

因为实际开发并不像我举的例子这么简单,肯定有数据交互的啦,往往各个策略需要的数据又不完全一样,会有重复也会有差异,引入了context后,我们的客户端就只要和context打交道,数据交互也是由context和策略类直接交互,可以理解为context是一个缓冲地带,在这里我们可以在调用策略类之前做些小动作、处理策略类需要的数据。

然后如果有策略类被删除或者新增替换,又或者是改名,在被很多模块调用的情况下,需要一个一个去修改,容易出错又麻烦。引入context后只用修改context的映射就可以了。

传送门:

(77条消息) isS1mple??的博客_CSDN博客-领域博主