小白设计模式:策略模式

331 阅读4分钟

定义

策略模式(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者分离后可以去除在各个子类单独实现算法的重复部分;

缺点

  1. 比起将"可变"与"稳定"部分都放一起来讲,类数目会增加比较多(大部分设计模式都会这样)

应用场景

  1. 许多相同的类,但是仅仅是行为不一致,就可以使用策略模式,将不同的行为抽象接口,实现成各个行为算法类;
  2. 单个类中,存在许多行为,但是在某些调用的地方需要使用if来判断不同的行为,则可以将这些行为用策略模式优化;

微信公众号