1、定义
策略模式作为一种软件设计模式,指对象有某个行为,但是在不同的场景中,该行为有不同的实现算法。比如每个人都要“交个人所得税”,但是“在美国交个人所得税”和“在中国交个人所得税”就有不同的算税方法。
策略模式:
* 定义了一族算法(业务规则);
* 封装了每个算法;
* 这族的算法可互换代替(interchangeable)。
摘自维基百科:(https://zh.wikipedia.org/wiki/%E7%AD%96%E7%95%A5%E6%A8%A1%E5%BC%8F)
2、说明
策略模式属于对象的行为模式。它的目的是定义一系列算法,把它们一个个封装起来, 并且使得它们可相互替换。比如,代码中有很多算法夹在在一个方法中,或者有很多种情况需要处理,但使用的是if…else…进行处理。这样,时间长了代码就会发酵、腐烂,难以维护。比较好的解决方法是将这些算法分离开来,抽象出接口,使用一个context上下文来注入这个接口,使得在需要某一算法的时候,可以直接通过上下文去获取,降低了代码的复杂度,相应代码的可读性也会提高。
策略模式的适用场景大致有:(1)如果很多相关的类仅仅是行为有异,“策略”则可以提供用行为来配置一个类的方法,即一个系统可按需动态在若干策略中进行选择;(2)需要对客户隐藏复杂的且与算法相关的数据结构;(3)类定义了多种行为,且这些行为在类中以多条件语句的形式出现。
3、角色
环境角色(Context):持有对Strategy的引用。
抽象策略角色(Strategy):通常由一个接口或抽象类实现,此角色给出所有的具体策略类所需的接口,并有具体策略类去实现。
具体策略角色(ConcreteStrategy):包装了相关的算法或行为,需要实现抽象策略类。
4、类图
5、示例
/**
* 策略接口类
* @author liqqc
*
*/
public interface IStrategy {
/*
* 获取价格
*/
public double getPrice(double price);
}
/**
*
* @author liqqc
*
*/
public class Context {
private IStrategy iStrategy;
public Context(IStrategy strategy) {
this.iStrategy = strategy;
}
public Double getQuota(Double price) {
return this.iStrategy.getPrice(price);
}
}
/**
* 一般用户
* @author liqqc
*
*/
public class GeneralUser implements IStrategy {
@Override
public double getPrice(double price) {
System.err.println("you are general user");
return price;
}
}
/**
* 普通会员
* @author liqqc
*
*/
public class VipUser implements IStrategy {
@Override
public double getPrice(double price) {
System.err.println("you are vip ,can get disaccount");
return price * 0.9;
}
}
/**
* 高级会员
* @author liqqc
*
*/
public class HighVipUser implements IStrategy {
@Override
public double getPrice(double price) {
System.err.println("you are high vip, can get a high discount");
return price * 0.5;
}
}
/**
* 测试
* @author liqqc
*
*/
public class Main {
public static void main(String[] args) {
final Double price = 1000.0;
//high vip
IStrategy highVipUser = new HighVipUser();
Context context1 = new Context(highVipUser);
Double discount1 = context1.getQuota(price);
System.err.println("you need pay : " + discount1 + "RMB");
System.err.println();
//vip
IStrategy vipUser = new VipUser();
Context context2 = new Context(vipUser);
Double discount2 = context2.getQuota(price);
System.err.println("you need pay : " + discount2 + "RMB");
System.err.println();
//general
IStrategy generalUser = new GeneralUser();
Context context3 = new Context(generalUser);
Double discount3 = context3.getQuota(price);
System.err.println("you need pay : " + discount3 + "RMB");
}
}
运行结果:
you are high vip, can get a high discount
you need pay : 500.0RMB
you are vip ,can get disaccount
you need pay : 900.0RMB
you are general user
you need pay : 1000.0RMB
6、总结
优点:(1)策略模式提供了一种管理相关类型算法的办法。其中,策略类的层级结构定义了若干算法或行为。如果能在其中恰当地使用抽象和继承,可以把公共的代码移到父类中,进而避免代码重复。(2)对于使用大量多重条件(if-else)的代码,使用策略模式可以很好地将其减少消除。由于多重条件语句难以维护,其将算法或行为的逻辑混合在一起,全包在一个多重条件语句里面,阅读起来也很费劲,在开发中应该减少多重条件的使用。
缺点:(1)对于使用者而言,必须知道所有策略类,并按照需求决定使用哪一个策略类。也就意味使用者必须理解策略类(算法)间的异同,以便选择恰当的策略类,策略模式只适用于使用者知道(策略类)算法或行为的情况下使用。对对于一些特别复杂的算法,也不建议使用。(2)策略模式把具体策略实现都封装成为一个一个的类,如果可选的策略很多的话,那么策略类的数数量会很大,可能会难以维护。
本文只是简单介绍了策略模式,并未对其进行深入探讨,略显粗糙。希望本文对你有所帮助。