Java设计模式——策略模式

策略模式

在策略模式(Strategy Pattern)中,一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。摘自菜鸟教程

个人理解就是:有许多类似或相同,并且经常改变的算法,我们把他们抽取出来声明接口,并把每个算法都实现了。到时候动态调用该方法的实现类就好了。

策略模式需要:

  • 一个策略接口或者抽象类
  • 实现策略接口或者抽象类的多个子类
  • 获取算法的一个公共类。

注:一下代码都不存在优化:只是简单的理解一下模式。

下面代码演示:

就简单的加减乘除吧

 创建运算"工厂",带引号工厂,跟工厂模式无关

/**
 * 运算接口,所有算法的"工厂"
 *
 * @author: wanghao
 * @Date:  2018/5/12 下午3:34
*/
interface Operation{

    double operation(double d1,double d2);
}

创建三个运算类

/**
 * 加法实现
 *
 * @author: wanghao
 * @Date:  2018/5/12 下午3:38
*/
class Addition implements  Operation{

    @Override
    public double operation(double d1, double d2) {
        return d1 + d2;
    }
}
/**
 * 减法实现
 *
 * @author: wanghao
 * @Date:  2018/5/12 下午3:38
 */
class Multiplication implements  Operation{

    @Override
    public double operation(double d1, double d2) {
        return d1 * d2;
    }
}
/**
 * 乘法实现
 *
 * @author: wanghao
 * @Date:  2018/5/12 下午3:38
 */
class Multiplication implements  Operation{

    @Override
    public double operation(double d1, double d2) {
        return d1 * d2;
    }
}

创建获取算法工具类:

/**
 * 创建获取方法的工具类
 */
class Context{

    private Operation operation;

    Context(Operation operation){
        this.operation = operation;
    }

    public double operation(double d1,double d2){
        return operation.operation(d1,d2);
    }
}

然后创建测试类:注意注释,因为我知道了我需要什么算法,所以就选择了相应的算法。

public static void main(String [] args){
        Context context = new Context(new Addition());
        //因为我需要加法所以创建了加法对象
        System.out.println("5和3数相加的结果为:"+ context.operation(5,3));
        //现在我需要减法了,所以我重新创建减法对象
        context = new Context(new Subtraction());
        System.out.println("5和3两个数相减的结果为:"+ context.operation(5,3));
        //现在我需要乘法了,所以我重新创建乘法对象
        context = new Context(new Multiplication());
        System.out.println("5和3两个数相减的结果为:"+ context.operation(5,3));
    }

运行结果为:

看了上面的例子应该可以很好理解策略模式了吧,不过有些人会疑惑为什么跟工厂模式很像,其实跟工厂模式的确很像,只是工厂模式注重的是获取对象,而策略模式注重的是获取方法。或者说获取策略。或者这样理解,工厂模式产出的是类的实力,吐出来的是类的实例,而策略模式则是封装算法,不管出来的什么,只要是你想要的策略就行。或者工厂模式注重对象,而策略模式注重方法,或者注重过程。

工厂与策略的区别

相同场景,工厂模式与策略模式的区别。

下面再举个例子吧:

场景:某个商店对会员有优惠,分三个等级,普通会员=不打折,一级会员=九折,二级会员=8折,然后每次购买都算出金额。使用策略模式如下:

创建一个商品价钱接口,用于计算根据用户和会员不同计算不同的价钱:

/**
 *
 *
 * @Description:  商品价钱接口
 * @Author:       wanghao
 * @CreateDate:   2018/5/12  22:46
 *
 */
interface ProductPrice {
    double getPrice(double price);
}

创建普原价返回类,打九折类,打八折类:

/**
 * 原价返回算法,只是模拟场景,也可不调用这个方法
 */
class OriginalPrice implements ProductPrice{
    //普通用户折扣常量
    private  static final double DISCOUNT = 1;
    //普通用户原价返回
    public double getPrice(double price) {
        return price;
    }
}
/**
 * 打九折算法类
 */
class NineFold implements ProductPrice{
    //一级会员折扣常量
    private  static final double DISCOUNT = 0.9;
    //一级会员打九折
    public double getPrice(double price) {
        return price * DISCOUNT;
    }
}
/**
 * 打八折算法类
 */
class EightFold implements ProductPrice{
    //二级会员折扣常量
    private  static final double DISCOUNT = 0.8;
    //二级会员打八折
    public double getPrice(double price) {
        return price * DISCOUNT;
    }
}

创建商店类,包含计算商品价钱类,

/**
 *
 *
 * @Description:  商店类
 * @Author:       wanghao
 * @CreateDate:   2018/5/12  22:53
 *
 */
class Shop {
    //专门计算用户商品价钱的类
    private ProductPrice productPrice;
    //因为可能商店有很多功能,所以不从构造参数那边传入参数了,直接set进去
    public void setProductPrice(ProductPrice productPrice){
        this.productPrice = productPrice;
    }
    //计算后返回价钱
    public double getPriceByUser(double d1){
       return productPrice.getPrice(d1);
    };
}

创建Demo类测试:

/**
 *
 * 策略模式测试类
 *
 * @Author:       wanghao
 * @CreateDate:   2018/5/12  22:44
 *
 */
public class StrategiesPatternDemo {
    public static void main (String [] args){
        //获取商店类
        Shop shop = new Shop();
        //模拟普通用户购买了一个商品100元,知道是原价,所以就调用原价的算法
        shop.setProductPrice(new OriginalPrice());
        double price = 100;
        System.out.println("尊敬的普通用户:商品价格为:"+price+",实际支付为:"+shop.getPriceByUser(100));

        //模拟一级会员用户购买了一个商品100元,所以调用九折算法
        shop.setProductPrice(new NineFold());
        System.out.println("尊敬的一级会员:商品价格为:"+price+",实际支付为:"+shop.getPriceByUser(100));

        //模拟二级会员用户购买了一个商品100元,所以调用八折算法
        shop.setProductPrice(new EightFold());
        System.out.println("尊敬的二级会员:商品价格为:"+price+",实际支付为:"+shop.getPriceByUser(100));
    }
}

 

运行结果为:

这样就是根据不同的用户采用不同的策略,

 

下面使用工程模式写一下上面的场景,大家可以对比一下工厂模式与策略模式的区别,

大家还记得工厂模式吗?如果不记得可以看我之前发表文章关于工厂模式的,可点击进去————》Java设计模式——单例模式+工厂模式

 下面是代码的实现:

 创建一个商店用户工厂类:

/**
 *
 *
 * @Description:  商店用户工厂
 * @Author:       wanghao
 * @CreateDate:   2018/5/12  23:58
 * 注:因为跟上面的shop 重名所以我就写了shop2,请忽略
 */
class ShopUserFactory {
    public static <T extends ShopUser> T  getShopUser(Class<T> clz) {
        T t = null;
        try {
            t = (T) Class.forName(clz.getName()).newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return  t;
    }
}

创建用户接口:

/**
 *
 *
 * @Description:  只针对上面的场景
 * @Author:       wanghao
 * @CreateDate:   2018/5/12  23:52
 *
 */
abstract class   ShopUser{
    //存储用户等级
    String userLevel ;
    abstract double getPrice(double price);

    public void setUserLevel(String userLevel){
        this.userLevel = userLevel;
    }
}

创建普通用户,一级用户,二级用户类:

class NoMember extends ShopUser {
    //非会员折扣常量
    private  static final double DISCOUNT = 1;
    /**
     * 非会员用户
     * @param price
     * @return
     */
    @Override
    double getPrice(double price) {
        return price * DISCOUNT;
    }
}
class OneMember extends ShopUser {
    //一级会员折扣常量
    private  static final double DISCOUNT = 0.9;
    /**
     * 一级会员用户
     * @param price
     * @return
     */
    @Override
    double getPrice(double price) {
        return price * DISCOUNT;
    }
}
class TwoMember extends ShopUser {
    //二级会员折扣常量
    private  static final double DISCOUNT = 0.8;
    /**
     * 二级会员用户
     * @param price
     * @return
     */
    @Override
    double getPrice(double price) {
        return price * DISCOUNT;
    }
}

创建测试类:

double price = 100;
        //刷卡的的时候确认不是会员,r然后获取不是会员实例
        ShopUser shopUser = ShopUserFactory.getShopUser(NoMember.class);
        //设置用户身份
        shopUser.setUserLevel("普通用户");
        //模拟结账
        System.out.println("尊敬的"+shopUser.userLevel+"你购买了:"+price+",实际应支付:"+shopUser.getPrice(price));

        //刷卡的的时候确认是一级会员,r然后获取一级会员实例
        shopUser = ShopUserFactory.getShopUser(OneMember.class);
        //设置用户身份
        shopUser.setUserLevel("一级会员");
        //模拟结账
        System.out.println("尊敬的"+shopUser.userLevel+"你购买了:"+price+",实际应支付:"+shopUser.getPrice(price));


        //刷卡的的时候确认是二级会员,r然后获取二级会员实例
        shopUser = ShopUserFactory.getShopUser(TwoMember.class);
        //设置用户身份
        shopUser.setUserLevel("二级会员");
        //模拟结账
        System.out.println("尊敬的"+shopUser.userLevel+"你购买了:"+price+",实际应支付:"+shopUser.getPrice(price));

打印结果为:

主要是策略模式和工厂模式有点类似,所以本篇文章后面写的就是他们两个模式的区别。

个人觉得:

工厂模式针对对象实例,策略模式针对策略也就是方法。

 

其实后面几个模式挺心虚的,因为本人也是现学现总结,如果那里不对,可以指出来一起探讨,欢迎大家一起探讨。

posted @ 2018-05-13 00:42  苦心明  阅读(404)  评论(0)    收藏  举报