@pastqing
2015-10-21T03:03:24.000000Z
字数 4388
阅读 3420
java 设计模式
策略模式, 顾名思义就是指对象具有某个行为,但是在不同的业务场景下, 这个行为应该有不同的表现形式, 也就是有了不同的策略。让对象能再不同的场景下对同一行为有不同的实现, 这就是策略模式。
下面是策略模式的类图:

public interface Strategy {public void algorithmStartegy() ;}
public class ConcentrateStrategy_1 implements Strategy{@Overridepublic void algorithmStartegy() {System.out.println("I am algorithm strategy 1");}}public class ConcentrateStrategy_2 implements Strategy{@Overridepublic void algorithmStartegy() {System.out.println("I am algorithm strategy 2");}}
public class Situation {Strategy strategy;public Situation(Strategy strategy) {this.strategy = strategy;}public void handleAlgorithm() {strategy.algorithmStartegy();}}
Situation situation = new Situation(new ConcentrateStrategy_1());situation.handleAlgorithm();...
从策略模式的描述以及类图来看真的是非常简单, 总结起来就是策略模式定义了一组算法,它们有一个共同的策略行为接口 ,并且这些算法之间可以互相替换,使算法可以根据场景的不同而改变。
策略模式的应用有很多, 比如说JDK中FilenameFilter的使用过程, 比如场景java.util.Collections.sort(List<T>list, Comparator<? super T>c)与策略java.util.Comparator的使用等等。下面我以一个实际的业务场景来具体实现以下策略模式:
1、背景: 中国银行的便民服务包括中国移动手机充值, 中国联通,中国电信。用户选择某个便民服务时, 服务器后台会向银行发送不同的业务XML报文, 已达到通信目的。
2、实现
定义策略接口 : 包含一个生成报文的方法
public interface IProduct {public String generateXML() ;}
定义一组具体策略类:
@XMLType("Default")class DefaultHead implements IProduct {public String generateXML() {return "Defalut XML";}}@XMLType("ChinaMobile")class ChinaMobile implements IProduct{public String generateXML() {return "China Mobile XML";}}@XMLType("ChinaUnicom")class ChinaUnicom implements IProduct {public String generateXML() {return "Chinal Unicom XML";}}...
注解先不管, 后文会有解释。
public class XMLGenerator {private IProduct product = new DefaultHead();//根据用户缴费类型,生成不同的通信报文public String generate(String type) {//注意此处product = ProductFactory.getInstance().createProduct(type);return product.generateXML();}}
创建具体的策略类, 本来是可以用一系列的if else判断, 然后new相应的策略类。这里为了避免if else我们定义一个策略工厂,来生产具体的策略类。
public class ProductFactory {// singletonprivate ProductFactory() {}public static ProductFactory getInstance() {return ProductFactoryInstance.instance;}private static class ProductFactoryInstance {static final ProductFactory instance = new ProductFactory();}//创建一个具体的策略类public IProduct createProduct(String productType) throws URISyntaxException {// load all startegysList<Class<? extends IProduct>> startegyList = loadAllStrategy("com.su.startegy");//遍历所有策略类, 根据条件找出需要用到的for(Class<? extends IProduct> clazz : startegyList) {//解析策略类的注解XMLType xmlType = praseAnnotation(clazz);if(xmlType.value().equals(productType))try {return clazz.newInstance();} catch (InstantiationException | IllegalAccessException e) {e.printStackTrace();}}//create IProduct Object failedreturn null;}//载入策略类方法private List<Class<? extends IProduct>> loadAllStrategy(String packageName) throws URISyntaxException {//定义一个策略类的列表List<Class<? extends IProduct>> strategyList = new ArrayList<Class<? extends IProduct>>();URI filePath = getClass().getClassLoader().getResource(packageName.replace(".", "/")).toURI();//获取filepathFile[] files = new File(filePath).listFiles(new FilenameFilter() {@Overridepublic boolean accept(File dir, String name) {if (name.endsWith(".class"))return true;return false;}});// load classfor (File file : files) {try {Class clazz = getClass().getClassLoader().loadClass(packageName + "." + file.getName().replace(".class", ""));if (clazz != IProduct.class && IProduct.class.isAssignableFrom(clazz)) {strategyList.add(clazz);}} catch (ClassNotFoundException e) {e.printStackTrace();}}return strategyList;}//解析注解方法private XMLType praseAnnotation(Class<? extends IProduct> clazz) {XMLType xmlType = clazz.getAnnotation(XMLType.class);if (xmlType == null) {return null;}return xmlType;}
此处我使用注解的原因是为了简单, 跟代码的耦合紧一点。
@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)public @interface XMLType {public String value() default "defalut";}
以上就是此处的策略模式的设计过程,如果需要多种策略的叠加, 也就要相应的使用注解的嵌套了, 这里就不在发挥了。
学习策略模式, 不要记住代码是怎么实现的,更重要的是记住其设计原则。根据原则写代码, 而不是生搬硬套。其实设计模式都是设计原则的体现, 如果理解了设计原则, 那么你写的代码也可以变成一种模式。
1、开闭原则(Open-Closed Principle,缩写为OCP)
2、里氏替换原则(Liskov Substitution Principle,缩写为LSP)
参考文献
策略模式设计原则