Java设计模式——策略模式(Strategy Pattern)

一、策略模式的定义

        定义:策略模式定义了一系列的算法,并将每一个算法封装起来,而且使他们可以相互替换,让算法独立于使用它的客户而独立变化。

        分析:策略模式定义和封装了一系列的算法,他们是可以相互替换的,也就是说它们具有共性,而它们的共性就体现在策略接口的行为上,另外为了达到最后一句话的目的,也就是说让算法独立于使用它的客户而独立变化,我们需要让客户端依赖于策略接口。

二、策略模式的使用

        1.针对同一类型问题的多种处理方式,仅仅是具体行为有差别时;

        2.需要安全地封装多种同一类的操作时;

        3.出现同一抽象类有多个子类,而又需要使用if-else或者switch-case来选择具体子类时。

三、策略模式使用的目的

        使用策略模式(同样针对于所有的方案设计)的时候,需要对项目的扩展性,降低复杂度。分析项目中变化与不变的部分,提取变化的部分,抽象成接口+实现。

        面向对象编程,并不是类越多越好,类的划分是为了封装,但分类的基础是抽象,具有相同属性和功能的对象的抽象集合才是类,即区分这些类的只是他们的直接行为。

四、策略模式图

 

        这个模式涉及到三个角色:

               1.环境(Context)角色:持有一个Strategy的引用

               2.抽象策略(Strategy)角色:这是一个抽象角色,通常由一个接口或抽象类实现,此角色给出所有的具体策略类所需的接口。

               3.具体策略(ConcreteStrategy)角色:包装了相关的算法或行为。

       分别封装接口,实现算法族,超类里面 放行为接口对象,在子类里面具体设定行为接口对象,原则就是分离变化部分,封装接口,基于接口编程各种功能。

五、策略模式的典型

    抽象策略类

public interface Strategy {
	/**
	 * 策略方法
	 */
	void StrategyInterface();
}

    具体策略类

public class ConcreteStrategyA implements Strategy{

	@Override
	public void StrategyInterface() {
		// TODO Auto-generated method stub
		
		//相关业务
	}

}
public class ConcreteStrategyB implements Strategy{

	@Override
	public void StrategyInterface() {
		// TODO Auto-generated method stub
		
		//相关业务
	}

}
public class ConcreteStrategyC implements Strategy{

	@Override
	public void StrategyInterface() {
		// TODO Auto-generated method stub
		
		//相关业务
	}

}

    环境角色类

public class Context {
	
	//持有一个具体策略的对象
	private Strategy strategy;
	
	/**
	 * 构造函数,传入一个具体策略对象
	 * @param strategy 具体策略对象
	 */
	public Context(Strategy strategy){
		this.strategy = strategy;
	}
	
	/**
	 * 策略方法
	 */
	public void contextInterface(){
		strategy.StrategyInterface();
	}
	
}
六、策略模式实例

某网站推出3种会员,分别为会员,超级会员和黄金会员,还有普通人,针对不同类别的顾客,购买东西时有不同的打折方式,并且一个顾客每消费10000就增加一个级别,普通人原价,会员打九折,超级会员打八折,黄金会员打七折,那么就可以使用策略模式。

策略接口

public interface CalPrice  {
	/**
	 * 最终价格
	 */
	double CalPrice (double orgnicPrice);
}

策略接口实现

public class Orgnic  implements CalPrice{

	@Override
	public double CalPrice(double orgnicPrice) {
		// TODO Auto-generated method stub
		return orgnicPrice;
	}
}
public class Vip implements CalPrice {

	@Override
	public double CalPrice(double orgnicPrice) {
		// TODO Auto-generated method stub
		return orgnicPrice * 0.9;
	}
}
public class SuperVip  implements CalPrice {

	@Override
	public double CalPrice(double orgnicPrice) {
		// TODO Auto-generated method stub
		return orgnicPrice * 0.8;
	}
}
public class GoldVip implements CalPrice {

	@Override
	public double CalPrice(double orgnicPrice) {
		// TODO Auto-generated method stub
		return orgnicPrice * 0.7;
	}
}

环境角色

public class Context {
	
	private double totalAmount = 0;//消费的zonge
	private double amount = 0;//单次消费
	private CalPrice calPrive = new Orgnic();//策略
	
	public void buy(double amount){
		this.amount = amount;
		totalAmount += amount;
		if(totalAmount >= 30000){
			calPrive = new GoldVip();
		}else if(totalAmount >= 20000){
			calPrive = new SuperVip();
		}else if(totalAmount >= 10000){
			calPrive = new Vip();
		}
	}
	
	public double calLastAmount(){
		return calPrive.CalPrice(amount);
	}
	
}
七、策略模式的注意点

    1.分析项目的变化部分(当前存在的变化部分以及项目后期迭代可能存在的变化部分)与不变化部分

    2.多用组合,少用继承,用行为类的组合,而不是行为的继承(继承会使得父类的影响扩展到所有子类),更有弹性

    3.如果一个系统的策略多于四个,就需要考虑使用混合模式,解决策略类膨胀的问题。

       策略模式时用来封装算法的,但在实践中,发现可以用它来封装几乎任何类型规则,只要在分析过程中听到需要在不同时间应用不同的业务规则,就可以考虑使用策略模式处理这种可能发生的变化。

        但是在策略模式中,选择所用具体实现的职责由客户端对象承担,并转给策略模式使用对象,这本身并没有解除客户端需要选择判断的压力,解决这一问题的方法是使用策略模式和简单工厂模式结合,选择具体实现的职责也由策略实用类Context来承担,这就最大化减轻了客户端的职责。


猜你喜欢

转载自blog.csdn.net/chaoyue1861/article/details/80769067