《Head First设计模式》之策略模式

   前段时间研究了数据结构,最近一段时间在看设计模式的书,感觉还是有些收获的,所以不才妄自拙笔打算写些设计模式的博客,和志同道合的朋友一起学习。

   如果看过了《大话设计模式》和《head first 设计模式》的话,本文参考这两本书,个人推荐head first的书,因为它用的语言是Java,大话用的是C#,主要原因还是head first的书总结的更全一些,特别是思考的过程和there are no dumb questions等感觉特别有意思,对比策略模式的例子的话还是大话的书中的例子更形象,更容易理解。对于策略模式,大话书上用的是抽象类的方式,而head first用的是接口的方式,感觉用接口的方式更符合策略模式,因为Java和C#语言都不支持多继承,如果这个类需要继承某个类的特性的话,就……

   大话中的例子说的是对于商场打折的促销活动,正常情况是全额,节假日可能对商品打八折、可能打n折,可能满300送100,可能满200送50……

   没有学设计模式之前,我们就是对于每一种不同的促销方式分别写一个类,就是完全用具体类实现,相信学习过策略模式之后,我们知道应该把这样的算法族封装起来,我改写了大话书上的实现方式,不过原理都一样。

   第一个和大家分享的设计模式是策略模式:定义了算法族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。看图就明白了


而我实现正是参考这张图

首先是抽象出算法来的策略类

package mystrategy;

public interface Promotion {
	public double discount(double money);
}
然后是三种不同价格的具体策略类

全价类

package mystrategy;

public class FullPrice implements Promotion{
	
	public double discount(double money) {
		return money;
	}
}
打折价类

package mystrategy;

public class DiscountPrice implements Promotion{
	private final double FACOTR = 0.8;  
	
	public double discount(double money) {
		return money*FACOTR;
	}
}
返利类,这里只是简单的实现,和大话还是有些出入

package mystrategy;

public class ReturnPrice implements Promotion {
	private final double MONEY_CONDITION = 300;
	private final double MONEY_RETURN = 100;
	
	public double discount(double money) {
		if(money>MONEY_CONDITION){
			return money-MONEY_RETURN;
		}
		return money;
	}
}
然后是Context上下文,其实就是用来对策略类的引用,这里是接口

package mystrategy;

public class Context {
	private Promotion promotion;

	public void setPromotion(Promotion promotion) {
		this.promotion = promotion;
	}
	
	public double getPayMoney(double money){
		return promotion.discount(money);
	}
}
最后是测试类

package mystrategy;

import java.util.Scanner;

public class TestStrategy {
	public static void main(String[] args) {
		int choice = 0;
		double money;
		Context context = new Context();
		Scanner reader = new Scanner(System.in);
		while(choice!=-1){
			money = 400;
			choice = reader.nextInt();
			switch (choice) {
			case 1:
				System.out.print("全价:");
				context.setPromotion(new FullPrice());
				break;
			case 2:
				System.out.print("折扣价(0.8折):");
				context.setPromotion(new DiscountPrice());
				break;
			case 3:
				System.out.print("超过300返100:");
				context.setPromotion(new ReturnPrice());
				break;
			default:
				break;
			}
			money = context.getPayMoney(money);
			System.out.println(money);
		}
		reader.close();
	}
}

其实不管我们用的是接口,还是抽象类,原理相同。

head first对此总结了三条设计原则

1.找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起

2.针对接口编程,而不是针对实现编程。

3.多用组合,少用继承


    感觉策略模式其实就是针对第二条来说的,策略模式就是实现一个接口,当然这里取的是广义的意思,实现一个接口泛指实现某个超类型(可以是类或接口)的某个方法,策略模式利用面向接口编程的特性,在运行时采取了多态,这样就不会依赖于具体类,如果用传统的方法,必然要和具体类挂钩。

   策略模式的实际应用,spring对于底层资源的访问全部依赖于resource接口,而这个接口就是一个典型的策略接口,他的实现类有UrlResource、ClassPathResource、FileSystemResouce、InputStreamResource等,不同的实现类代表了不同的资源访问策略。,而在spring中等同于策略模式中的Context类是ResouceLoader接口,该接口中有方法:Resource getResource(String location)。相信用过spring的朋友一定知道,我们获得应用上下文都是这样

<span style="font-family:Microsoft YaHei;">ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");</span>

其实ApplicationContext接口继承了ResourcePatternResolver,而ResourcePatternResolver继承了ResourceLoader接口,这里的ApplicationContext就相当于上面的主类。


1.先看Resource接口,相当于Strategy策略类




2.这里只列出Resource接口其中的一个实现类UrlResource,其中具体类UrlResource继承抽象类AbstractFileResolvingResource,抽象类AbstractFileResolvingResource继承抽象类AbstractResource,抽象类AbstractResource实现Resource接口,相当于UrlRsource间接实现了Resource,相当于策略模式中的具体策略类


3.再看ResourceLoader接口,主要是Resource getResource(String location);方法,相当于Context上下文



如果文章有什么错误或者有什么建议,欢迎提出,大家共同交流,一起进步

文章转载请注明出处,请尊重知识产权

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值