策略模式
发布日期:2021-09-25 11:48:12 浏览次数:1 分类:技术文章

本文共 4135 字,大约阅读时间需要 13 分钟。

定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户。

例子:商场收银,营业员根据客户所购买商品的单价和数量,向客户收费,但有时候会有打折或者满减活动,eg:打八折,满300送100

先用上个学习到的简单工厂实现一下

建立一个现金收费的抽象类

package celv;abstract class CashSuper {//	现金收取超类的抽象方法,收取现金,参数为原价,返回伪当前价	public abstract double acceptCash(double money);}

正常收费子类

package celv;public class CashNormal extends CashSuper{	@Override	public double acceptCash(double money) {		// TODO Auto-generated method stub		return money;	}}

折扣收费子类

package celv;public class CashRebate extends CashSuper{	public double moneyRebate=1;	public CashRebate(String moneyRebate){		this.moneyRebate=Double.parseDouble(moneyRebate);	}	@Override	public double acceptCash(double money) {		// TODO Auto-generated method stub		return money*moneyRebate;	}}

满减收费子类

package celv;public class CashReturn extends CashSuper{	public double moneyCondition=0.0;	public double moneyReturn=0.0;	public CashReturn(String moneyCondition,String moneyReturn){		this.moneyCondition=Double.parseDouble(moneyCondition);		this.moneyReturn=Double.parseDouble(moneyReturn);	}	@Override	public double acceptCash(double money) {		// TODO Auto-generated method stub		double result=money;		if(money>=moneyCondition){			result=money-Math.floor(money/moneyCondition)*moneyReturn;		}		return result;	}}

一个工厂类来生成不同实例

package celv;public class CashFactory {	public static CashSuper createCashAccept(String type){		CashSuper cs=null;		switch(type){		case "收费正常":			CashNormal cs0=new CashNormal();			cs=cs0;			break;		case "满300返100":			CashReturn cr1=new CashReturn("300","100");			cs=cr1;			break;		case "打八折":			CashRebate cr2=new CashRebate("0.8");			cs=cr2;			break;		}		return cs;	}}

测试

package celv;public class Test {	public static void main(String[] args) {		// TODO Auto-generated method stub		double price=50;		double number=20;		double total=0;		String type="满300返100";//		简单工厂模式		CashSuper csuper=CashFactory.createCashAccept(type);	        total=csuper.acceptCash(price*number);		System.out.println(total);			}}

上述可以完成基本功能要求,但是,工厂本身包括了所有的收费方式,商场是可能经常性地更改打折额度和返利额度,每次维护或扩展收费方式都要改动这个工厂,以至于代码需要重新编译部署。

策略模式:商场收银时如何促销,打折还是返利,其实都是一些算法,用工厂来生成算法对象没有错,但算法本身只是一种策略,最重要的是这些算法是随时都可能互相替换的,这就是变化点,封装变化点是面向对象的一种很重要的思维方式。

于是,可以不用工厂,建立一个Context上下文,用一个ConcreteStrategy来配置,维护一个对Strategy对象的应用,即:

package celv;public class CashContext {	public CashSuper cs;//	通过构造方法,传入具体的收费策略	public CashContext(CashSuper cs){		this.cs=cs;	}	//	根据收费策略的不同,获得计算结果	public double getResult(double money){	    return cs.acceptCash(money);	}	}

此时,客户端的测试可以写为:

package celv;public class celvTest {	public static void main(String[] args) {		// TODO Auto-generated method stub		double price=50;		double number=20;		double total=0;		String type="满300返100";				CashContext cc=null;		switch(type){		case "收费正常":			cc=new CashContext(new CashNormal());			break;		case "满300返100":			cc=new CashContext(new CashReturn("300","100"));			break;		case "打八折":			cc=new CashContext(new CashRebate("0.8"));			break;		}	    total=cc.getResult(price*number);		System.out.println(total);			}}

但是也存在缺点,即让客户端去判断用哪一个算法,可以试着将简单工工厂和策略模式进行结合,将CashContext类修改

package celv;public class CashContext {	public CashSuper cs;//	通过构造方法,传入具体的收费策略	public CashContext(CashSuper cs){		this.cs=cs;	}		public CashContext(String type){		switch(type){		case "收费正常":			CashNormal cs0=new CashNormal();			cs=cs0;			break;		case "满300返100":			CashReturn cr1=new CashReturn("300","100");			cs=cr1;			break;		case "打八折":			CashRebate cr2=new CashRebate("0.8");			cs=cr2;			break;		}	}//	根据收费策略的不同,获得计算结果	public double getResult(double money){	    return cs.acceptCash(money);	}	}

那么,客户端代码就是这样子

package celv;public class Test {	public static void main(String[] args) {		// TODO Auto-generated method stub		double price=50;		double number=20;		double total=0;		String type="满300返100";		//		策略模式与简单工厂结合		CashContext csuper=new CashContext(type);	        total=csuper.getResult(price*number);		System.out.println(total);			}}

由此可以看出,简单工厂模式让客户端认识两个类,即CashSuper和CashFactory,而策略模式与简单工厂结合,客户端只需要认识一个类CashContext,耦合度更低。

总结:策略模式是一种定义一系列算法的方法,从概念上看,所有这些算法完成的都是相同的工作,只是实现不同,它可以以相同的方式调用所有的算法,减少了各种算法类与使用算法类之间的耦合。简化了单元测试,因为每个算法都有自己的类,可以通过自己的接口单独测试。

参考自《大话设计模式》,代码自己有所修改,持续更新。

转载地址:https://blog.csdn.net/Autumn03/article/details/80740193 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:装饰者模式
下一篇:简单工厂模式-工厂方法模式

发表评论

最新留言

哈哈,博客排版真的漂亮呢~
[***.90.31.176]2024年04月15日 07时09分06秒