策略模式
在策略模式(Strategy Pattern)中,一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。摘自菜鸟教程
个人理解就是:有许多类似或相同,并且经常改变的算法,我们把他们抽取出来声明接口,并把每个算法都实现了。到时候动态调用该方法的实现类就好了。
策略模式需要:
一个策略接口或者抽象类
实现策略接口或者抽象类的多个子类
获取算法的一个公共类。
注:一下代码都不存在优化:只是简单的理解一下模式。
下面代码演示:
就简单的加减乘除吧
创建运算"工厂",带引号工厂,跟工厂模式无关
/*** 运算接口,所有算法的"工厂"
*
*@author: wanghao
* @Date: 2018/5/12 下午3:34*/
interfaceOperation{double operation(double d1,doubled2);
}
创建三个运算类
/*** 加法实现
*
*@author: wanghao
* @Date: 2018/5/12 下午3:38*/
class Addition implementsOperation{
@Overridepublic double operation(double d1, doubled2) {return d1 +d2;
}
}
/*** 减法实现
*
*@author: wanghao
* @Date: 2018/5/12 下午3:38*/
class Multiplication implementsOperation{
@Overridepublic double operation(double d1, doubled2) {return d1 *d2;
}
}
/*** 乘法实现
*
*@author: wanghao
* @Date: 2018/5/12 下午3:38*/
class Multiplication implementsOperation{
@Overridepublic double operation(double d1, doubled2) {return d1 *d2;
}
}
创建获取算法工具类:
/*** 创建获取方法的工具类*/
classContext{privateOperation operation;
Context(Operation operation){this.operation =operation;
}public double operation(double d1,doubled2){returnoperation.operation(d1,d2);
}
}
然后创建测试类:注意注释,因为我知道了我需要什么算法,所以就选择了相应的算法。
public static voidmain(String [] args){
Context context= new Context(newAddition());//因为我需要加法所以创建了加法对象
System.out.println("5和3数相加的结果为:"+ context.operation(5,3));//现在我需要减法了,所以我重新创建减法对象
context = new Context(newSubtraction());
System.out.println("5和3两个数相减的结果为:"+ context.operation(5,3));//现在我需要乘法了,所以我重新创建乘法对象
context = new Context(newMultiplication());
System.out.println("5和3两个数相减的结果为:"+ context.operation(5,3));
}
运行结果为:
看了上面的例子应该可以很好理解策略模式了吧,不过有些人会疑惑为什么跟工厂模式很像,其实跟工厂模式的确很像,只是工厂模式注重的是获取对象,而策略模式注重的是获取方法。或者说获取策略。或者这样理解,工厂模式产出的是类的实力,吐出来的是类的实例,而策略模式则是封装算法,不管出来的什么,只要是你想要的策略就行。或者工厂模式注重对象,而策略模式注重方法,或者注重过程。
工厂与策略的区别
相同场景,工厂模式与策略模式的区别。
下面再举个例子吧:
场景:某个商店对会员有优惠,分三个等级,普通会员=不打折,一级会员=九折,二级会员=8折,然后每次购买都算出金额。使用策略模式如下:
创建一个商品价钱接口,用于计算根据用户和会员不同计算不同的价钱:
/***
*
* @Description: 商品价钱接口
* @Author: wanghao
* @CreateDate: 2018/5/12 22:46
**/
interfaceProductPrice {double getPrice(doubleprice);
}
创建普原价返回类,打九折类,打八折类:
/*** 原价返回算法,只是模拟场景,也可不调用这个方法*/
class OriginalPrice implementsProductPrice{//普通用户折扣常量
private static final double DISCOUNT = 1;//普通用户原价返回
public double getPrice(doubleprice) {returnprice;
}
}
/*** 打九折算法类*/
class NineFold implementsProductPrice{//一级会员折扣常量
private static final double DISCOUNT = 0.9;//一级会员打九折
public double getPrice(doubleprice) {return price *DISCOUNT;
}
}
/*** 打八折算法类*/
class EightFold implementsProductPrice{//二级会员折扣常量
private static final double DISCOUNT = 0.8;//二级会员打八折
public double getPrice(doubleprice) {return price *DISCOUNT;
}
}
创建商店类,包含计算商品价钱类,
/***
*
* @Description: 商店类
* @Author: wanghao
* @CreateDate: 2018/5/12 22:53
**/
classShop {//专门计算用户商品价钱的类
privateProductPrice productPrice;//因为可能商店有很多功能,所以不从构造参数那边传入参数了,直接set进去
public voidsetProductPrice(ProductPrice productPrice){this.productPrice =productPrice;
}//计算后返回价钱
public double getPriceByUser(doubled1){returnproductPrice.getPrice(d1);
};
}
创建Demo类测试:
/***
* 策略模式测试类
*
* @Author: wanghao
* @CreateDate: 2018/5/12 22:44
**/
public classStrategiesPatternDemo {public static voidmain (String [] args){//获取商店类
Shop shop = newShop();//模拟普通用户购买了一个商品100元,知道是原价,所以就调用原价的算法
shop.setProductPrice(newOriginalPrice());double price = 100;
System.out.println("尊敬的普通用户:商品价格为:"+price+",实际支付为:"+shop.getPriceByUser(100));//模拟一级会员用户购买了一个商品100元,所以调用九折算法
shop.setProductPrice(newNineFold());
System.out.println("尊敬的一级会员:商品价格为:"+price+",实际支付为:"+shop.getPriceByUser(100));//模拟二级会员用户购买了一个商品100元,所以调用八折算法
shop.setProductPrice(newEightFold());
System.out.println("尊敬的二级会员:商品价格为:"+price+",实际支付为:"+shop.getPriceByUser(100));
}
}
运行结果为:
这样就是根据不同的用户采用不同的策略,
下面使用工程模式写一下上面的场景,大家可以对比一下工厂模式与策略模式的区别,
大家还记得工厂模式吗?如果不记得可以看我之前发表文章关于工厂模式的,可点击进去————》Java设计模式——单例模式+工厂模式
下面是代码的实现:
创建一个商店用户工厂类:
/***
*
* @Description: 商店用户工厂
* @Author: wanghao
* @CreateDate: 2018/5/12 23:58
* 注:因为跟上面的shop 重名所以我就写了shop2,请忽略*/
classShopUserFactory {public static T getShopUser(Classclz) {
T t= null;try{
t=(T) Class.forName(clz.getName()).newInstance();
}catch(Exception e) {
e.printStackTrace();
}returnt;
}
}
创建用户接口:
/***
*
* @Description: 只针对上面的场景
* @Author: wanghao
* @CreateDate: 2018/5/12 23:52
**/
abstract classShopUser{//存储用户等级
String userLevel ;abstract double getPrice(doubleprice);public voidsetUserLevel(String userLevel){this.userLevel =userLevel;
}
}
创建普通用户,一级用户,二级用户类:
class NoMember extendsShopUser {//非会员折扣常量
private static final double DISCOUNT = 1;/*** 非会员用户
*@paramprice
*@return
*/@Overridedouble getPrice(doubleprice) {return price *DISCOUNT;
}
}
class OneMember extendsShopUser {//一级会员折扣常量
private static final double DISCOUNT = 0.9;/*** 一级会员用户
*@paramprice
*@return
*/@Overridedouble getPrice(doubleprice) {return price *DISCOUNT;
}
}
class TwoMember extendsShopUser {//二级会员折扣常量
private static final double DISCOUNT = 0.8;/*** 二级会员用户
*@paramprice
*@return
*/@Overridedouble getPrice(doubleprice) {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));
打印结果为:
主要是策略模式和工厂模式有点类似,所以本篇文章后面写的就是他们两个模式的区别。
个人觉得:
工厂模式针对对象实例,策略模式针对策略也就是方法。
其实后面几个模式挺心虚的,因为本人也是现学现总结,如果那里不对,可以指出来一起探讨,欢迎大家一起探讨。