设计模式之策略模式

时间:2022-04-29
本文章向大家介绍设计模式之策略模式,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

         策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。

UML:

//工厂方法,用来生产策略
public class DisCountRateFactory {
	private static final List<String> STRATEGY_LIST;// 策略列表
	private static final List<Class<? extends Discount>> STRATEGY_CLASS_LIST;// 策略列表
	private static final DisCountRateFactory FACTORY;
	static {
		FACTORY = new DisCountRateFactory();
		STRATEGY_LIST = new ArrayList<String>();
		STRATEGY_CLASS_LIST = new ArrayList<Class<? extends Discount>>();
		STRATEGY_LIST.add("discount.Common");
		STRATEGY_LIST.add("discount.GoldVip");
		STRATEGY_LIST.add("discount.BronzeVip");
		STRATEGY_LIST.add("discount.SilverVip");
	}

	@SuppressWarnings("unchecked")
	private void getClassByclsName() throws Exception {
		for (String strategy : STRATEGY_LIST) {
			Class<? extends Discount> cls = (Class<? extends Discount>) Class.forName(strategy);
			STRATEGY_CLASS_LIST.add(cls);
		}
	}

	/**
	 * 获取工厂实例
	 * 
	 * @return
	 */
	public static DisCountRateFactory getInstance() {
		return FACTORY;
	}

	// 返回类的注解
	private PriceRange handleAnnotation(Class<? extends Discount> clazz) {
		Annotation[] annotations = clazz.getDeclaredAnnotations();
		if (annotations == null || annotations.length == 0) {
			return null;
		}
		return (PriceRange) annotations[0];
	}

	public Discount returnDisCountByAonnotation(double money) {
		try {
			// 获取所有的class
			getClassByclsName();
			for (Class<? extends Discount> clazz : STRATEGY_CLASS_LIST) {
				// 获取该策略的注解
				PriceRange range = handleAnnotation(clazz);
				// 区间判断
				if (money > range.min() && money <= range.max()) {
					return clazz.newInstance();
				}
			}
			throw new RuntimeException();
		} catch (Exception e1) {
			throw new RuntimeException("get strategy failed!");
		}

	}

}


//策略选择
public class StrategySelector {
	private double money;

	private Discount disCount = new Common();

	public void buy() {
		Discount disCountRate = DisCountRateFactory.getInstance()
		        .returnDisCountByAonnotation(money);
		if (disCountRate != null)
		    disCount = disCountRate;

		disCount.disCount(money);
		// if (money > 1000 && money <= 2000) {
		// disCount = new BronzeVip();
		// } else if (money > 2000 && money <= 3000) {
		// disCount = new SilverVip();
		// } else if (money > 3000) {
		// disCount = new GoldVip();
		// }
		// disCount.disCount(money);
	}

	public void setMoney(double money) {
		this.money = money;
		buy();
	}

//策略定义
public interface Discount {
	void disCount(double price);
}
//其中一个实现
@PriceRange(max = 1000)
public class Common implements Discount {
	@Override
	public void disCount(double price) {
		System.out.println("原价:" + price + ",折扣:" + 0 + ",不享受vip优惠,应付:" + price);
	}

}

//test
StrategySelector s = new StrategySelector();
	    s.setMoney(1000);
	    System.out.println("-------------");
	    s.setMoney(2000);
	    System.out.println("-------------");
	    s.setMoney(3000);
	    System.out.println("-------------");
	    s.setMoney(4000);
	    System.out.println("-------------");
	    s.setMoney(5000);

//console:
原价:1000.0,折扣:0,不享受vip优惠,应付:1000.0
-------------
原价:2000.0,折扣:0.9,享受青铜vip优惠,应付:1800.0
-------------
原价:3000.0,折扣:0.8,享受白银vip优惠,应付:2400.0
-------------
原价:4000.0,折扣:0.7,享受黄金vip优惠,应付:2800.0
-------------
原价:5000.0,折扣:0.7,享受黄金vip优惠,应付:3500.0