前段时间研究了数据结构,最近一段时间在看设计模式的书,感觉还是有些收获的,所以不才妄自拙笔打算写些设计模式的博客,和志同道合的朋友一起学习。
如果看过了《大话设计模式》和《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;然后是Context上下文,其实就是用来对策略类的引用,这里是接口
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;
}
}
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上下文
如果文章有什么错误或者有什么建议,欢迎提出,大家共同交流,一起进步
文章转载请注明出处,请尊重知识产权