定义
策略模式(Strategy),是一种对象行为模式:定义一系列的算法,将可变的部分封装起来,使得它们可以相互替换,让变化的部分于独立调用它的客户而变化,不会导致调用方需要跟着修改。 (这边的"算法"指的是系统中经常会变的部分,可能是超类定义的行为,或者特征之类的)
主要组成
抽象策略接口(Strategy): 定义同一组算法的公共接口;
具体策略实现(Concrete Strategy): 实现具体的某种算法;
客户端(Client): 调用者,一般会有策略列表存放各种策略,根据需要选择不同的策略实现功能;
UML图
框架代码
Strategy:
public interface Strategy {
void AlgorithmInterface();
}
复制代码
Concrete Strategy:
public class ConcreteStrategyA {
@Override
public void AlgorithmInterface(){
//策略A的行为
}
}
public class ConcreteStrategyB {
@Override
public void AlgorithmInterface(){
//策略B的行为
}
}
复制代码
Client:
Strategy strategy = new ConcreteStrategyA();
//Strategy strategy = new ConcreteStrategyB();
//执行处不管理策略具体实现细节
strategy.AlgorithmInterface();
复制代码
具体例子
UML图
代码
Vehicle(Strategy策略模块):
/**
* 交通工具
*
*/
public interface Vehicle {
//使用指定交通工具出发,不关心该工具的操作细节
String go();
}
复制代码
Car:
public class Car implements Vehicle{
@Override
public String go() {
return "开小汽车前往目的地";
}
}
复制代码
Bilk:
public class Bilk implements Vehicle{
@Override
public String go() {
return "骑自行车前往目的地";
}
}
复制代码
Plane:
public class Plane implements Vehicle{
@Override
public String go() {
return "乘坐飞机前往目的地";
}
}
复制代码
PayMent(Strategy策略模块):
/**
* 支付方式
*
*/
public interface PayMent {
//不关心支付方式的操作流程,只关心付款结果
String cost();
}
复制代码
AliPay:
public class AliPay implements PayMent{
@Override
public String cost() {
return "使用支付宝流程付款";
}
}
复制代码
WeChat:
public class WeChat implements PayMent{
@Override
public String cost() {
return "使用微信流程付款";
}
}
复制代码
Crash:
public class Crash implements PayMent{
@Override
public String cost() {
return "使用现金流程付款";
}
}
复制代码
稳定部分TravelPlan(使用各种策略的地方): TravelPlan:
public abstract class TravelPlan {
//可变的策略模块
Vehicle vehicle;
PayMent payMent;
//公共稳定的操作接口
public void setVehicle(Vehicle vehicle) {
this.vehicle = vehicle;
}
public void setPayMent(PayMent payMent) {
this.payMent = payMent;
}
public void go() {
System.out.println((getGoTime() + payMent.cost() + vehicle.go() + getDestination()));
}
public abstract String getDestination();
public abstract String getGoTime();
}
复制代码
BeijingTravelPlan:
public class BeijingTravelPlan extends TravelPlan{
@Override
public String getDestination() {
return "北京";
}
@Override
public String getGoTime() {
return "2018.11.12.09:00";
}
}
复制代码
TaiWanTravelPlan:
public class TaiWanTravelPlan extends TravelPlan{
@Override
public String getDestination() {
return "台湾";
}
@Override
public String getGoTime() {
return "2018.11.13.10:00";
}
}
复制代码
简单使用:
//定义北京旅游计划
TravelPlan travelPlan = new BeijingTravelPlan();
travelPlan.setPayMent(new WeChat());
travelPlan.setVehicle(new Car());
travelPlan.go();
//告白出行交通工具和付款方式
travelPlan.setPayMent(new Crash());
travelPlan.setVehicle(new Bilk());
travelPlan.go();
日志输出:
2018.11.12.09:00使用微信流程付款开小汽车前往目的地北京
2018.11.12.09:00使用现金流程付款骑自行车前往目的地北京
复制代码
假设不使用策略模式
未将可变部分独立出来,即不存在Vehicle和PayMent这2个算法模块,则对于TravePlane继承体系可能为:
public abstract class TravelPlan {
String vehicleType;
String payMentType;
public void setVehicle(String vehicle) {
this.vehicleType = vehicle;
}
public void setPayMent(String payMent) {
this.payMentType = payMent;
}
public void go() {
System.out.println((getGoTime() + payMentCost() + vehicleGo() + getDestination()));
}
//存在一大堆条件判断
public String vehicleGo () {
switch (vehicleType) {
case "Car":
return "开小汽车前往目的地";
case "Bilk":
return "骑自行车前往目的地";
case "Plane":
return "乘坐飞机前往目的地";
default:
return null;
}
}
//存在一大堆条件判断
public String payMentCost () {
switch (vehicleType) {
case "AliPay":
return "使用支付宝流程付款";
case "WeChat":
return "使用微信流程付款";
case "Crash":
return "使用现金流程付款";
default:
return null;
}
}
public abstract String getDestination();
public abstract String getGoTime();
}
复制代码
经常会因为业务而发生修改扩展的部分都堆在了相对稳定的部分,没有面向接口通过组合的方式,后续修改vehicle和PayMent部分可能会不经意点影响到了其它功能点。
总结
优点
1.策略模式封装了可变部分,使得"可变"部分独立于"稳定"部分,在经常性的增加修改"可变"部分过程不需要动到"稳定"部分,可用于取代将全部行为封装到超类然后由每个子类都实现一遍的纯继承方式;
2.当算法种类多的时候,避免了一系列的条件判断,代码更简洁;
3.不同算法实现同一接口,可以互相替换,不需要硬编码到调用处;
4.2者分离后可以去除在各个子类单独实现算法的重复部分;
缺点
- 比起将"可变"与"稳定"部分都放一起来讲,类数目会增加比较多(大部分设计模式都会这样)
应用场景
- 许多相同的类,但是仅仅是行为不一致,就可以使用策略模式,将不同的行为抽象接口,实现成各个行为算法类;
- 单个类中,存在许多行为,但是在某些调用的地方需要使用if来判断不同的行为,则可以将这些行为用策略模式优化;
微信公众号