【设计模式】策略模式

策略模式是行为型设计模式,它允许定义一系列不同的算法,客户端可在不同的算法间轻松切换

1、使用

假设有一套支付系统,用户可以选择不同渠道支付,渠道有微信、支付宝、PayPal

public interface Pay {
	
	void pay();
	
}

支付宝支付

public class AliPay implements Pay {

	@Override
	public void pay() {
		System.err.println("支付宝支付");
	}
	
}

微信支付

public class WeixinPay implements Pay {

	@Override
	public void pay() {
		System.err.println("微信支付");
	}
	
}

PayPal支付

public class PayPalPay implements Pay {

	@Override
	public void pay() {
		System.err.println("PayPal支付");
	}
	
}

支付策略类

public class PayStrategies {
	
	private Map<String, Pay> payStrategies = new HashMap<>();

	public PayStrategies {
		payStrategies.put("ali", new AliPay());
		payStrategies.put("weixin", new WeiXinPay());
		payStrategies.put("paypal", new PayPalPay());
	}

	public Pay getPay(String strategies) {
		Pay pay = payStrategies.get(strategies);
		if (pay == null)
			throw new IllegalArgumentException();
		return pay;
	}

}

客户端

public class Client {

	public static void main(String[] args) {
		PayStrategies ps = new PayStrategies();
		Pay pay = ps.getPay("ali");
		pay.pay();
	}
	
}

客户端通过传递不同的参数,选择不同的支付方式进行支付

2、常见应用

1、SpringMVC中HandlerMethodArgumentResolver解析入参参数

public interface HandlerMethodArgumentResolver {

	/**
	 * Whether the given {@linkplain MethodParameter method parameter} is
	 * supported by this resolver.
	 * @param parameter the method parameter to check
	 * @return {@code true} if this resolver supports the supplied parameter;
	 * {@code false} otherwise
	 */
	boolean supportsParameter(MethodParameter parameter);

	/**
	 * Resolves a method parameter into an argument value from a given request.
	 * A {@link ModelAndViewContainer} provides access to the model for the
	 * request. A {@link WebDataBinderFactory} provides a way to create
	 * a {@link WebDataBinder} instance when needed for data binding and
	 * type conversion purposes.
	 * @param parameter the method parameter to resolve. This parameter must
	 * have previously been passed to {@link #supportsParameter} which must
	 * have returned {@code true}.
	 * @param mavContainer the ModelAndViewContainer for the current request
	 * @param webRequest the current request
	 * @param binderFactory a factory for creating {@link WebDataBinder} instances
	 * @return the resolved argument value, or {@code null} if not resolvable
	 * @throws Exception in case of errors with the preparation of argument values
	 */
	@Nullable
	Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
			NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception;

}

根据参数类型通过supportsParameter是否支持解析参数,支持的话就可以调用resolveArgument方法进行解析。常见的实现RequestParamMethodArgumentResolver解析带有@RequestParam注解的参数,ServletModelAttributeMethodProcessor解析自定义类型的参数,RequestResponseBodyMethodProcessor解析带有@RequestBody注解的参数

2、Collections.sort(List<T> list, Comparator<? super T> c)方法中,Comparator接口代表着一种排序的抽象策略,可以实现不同的Comparator(推荐使用Lambda实现),拥有不同的排序方式

3、总结

1、优缺点

优点

  • 自由选择不同算法
  • 符合开闭原则
  • 将算法的实现和算法的使用隔离

缺点

  • 客户端要知道策略间的不同才能选择不同的算法

2、应用场景

  • 希望使用不同的算法,并在运行时可以动态切换,可以使用策略模式

3、模版模式与策略模式

  • 模版方式基于继承,只能重写算法中的部分步骤
  • 策略模式基于组合,可以重写整个算法

版权声明:本文为weixin_42721350原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。