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));
打印结果为:

主要是策略模式和工厂模式有点类似,所以本篇文章后面写的就是他们两个模式的区别。
个人觉得:
工厂模式针对对象实例,策略模式针对策略也就是方法。
其实后面几个模式挺心虚的,因为本人也是现学现总结,如果那里不对,可以指出来一起探讨,欢迎大家一起探讨。

浙公网安备 33010602011771号