007 策略设计

一 .概述

如果把方法的实现作为一个参数,那么这个参数就是一个策略,很像我们常常使用的函数式编程.

二 .场景

一个简单的计算价钱的场景:

[1]普通用户所有的价钱为原价

[2]普通会员的九折

[3]黄金会员为八折.

我们一个简单的程序如下:

public class SimpleCounter {
    
    
    public double count(String type,double price) {
        // 普通会员
        if("commons".equals(type)) {
            return price ;
        }
         // 一般的会员
        else if("commonvip".equals(type)) {
            return price * 0.9;
        }
        // 黄金会员
        else {
            return price * 0.8;
        }
    }
}

在这里,我们可能常常出现的一个问题就是具体计算的方法会发生改变.也就是说我们的if这一部分的内容常常需要发生变化,

另外的一个问题,就是计算的种类也会发生变化,也就是说这一部分的方法是非常不稳定的.

我们由此引入一个策略的模式:

/**
 *  具体的策略,子类实现不同的计算接口 
 */
public interface Strategy {
    double count(double price);
}
public class CommonStrategy implements Strategy {
    
    public double count(double price) {
        return price;
    }
}
/**
 * 普通vip的实现
 */
public class CommonVipStrategy implements Strategy {

    public double count(double price) {
        return price * 0.9;
    }

}
/**
 * 超级vip的实现
 */
public class SuperVipStrategy implements Strategy{
    
    public double count(double price) {
        return price * 0.8;
    }
    
}
/**
 *  策略上下文
 */
public interface StrategyContext {

    Strategy getStrategy();
}
/**
 * 策略的上下文,主要用来封装一系列策略运行需要的参数
 */
public class SimpleStrategyContext implements StrategyContext {

    private Strategy strategy;

    public SimpleStrategyContext(Strategy strategy) {
        this.strategy = strategy;
    }

    public double count(double price) {
        return this.strategy.count(price);
    }

    public Strategy getStrategy() {
        return this.strategy;
    }
}
public class Client {

    public static void main(String[] args) {
        //Strategy strategy = new CommonStrategy();
        Strategy strategy = new SuperVipStrategy();
        SimpleStrategyContext context = new SimpleStrategyContext(strategy);
        double count = context.count(100d);
        System.out.println(count);
    }
}

现在我们可以通过这里创建不同的策略进行切换,保证的开闭原则.

现在出现了一个问题,我们每次都需要创建策略接口的子类,客户端在一定程度上就需要知道子类的实现情况.

在这个地方,我们可以使用工厂模式来解决这个问题.

毕竟工厂模式最主要的功能就是选择一个接口的实例的功能.


 三 . 策略模式的说明

通过一个策略上下文封装一个策略的具体实现.

然后客户端仅仅只需要和策略的上下文进行交互就可以完成了.

当然,在策略上下文之中,我们可以封装大量的参数信息,帮助策略对象工作的时候的需要.


 

posted @ 2019-03-29 16:39  最爱五仁月饼  阅读(123)  评论(0编辑  收藏  举报