0
点赞
收藏
分享

微信扫一扫

设计模式实战13--行为型--策略模式


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



策略模式让算法独立于使用它的客户而独立变化。


策略模式结构图:



 

设计模式实战13--行为型--策略模式_class

 



 



策略模式解析:



      Context(应用场景):



  1、需要使用ConcreteStrategy提供的算法。



  2、 内部维护一个Strategy的实例。



  3、 负责动态设置运行时Strategy具体的实现算法。



  4、负责跟Strategy之间的交互和数据传递。




  Strategy(抽象策略类):



  1、 定义了一个公共接口,各种不同的算法以不同的方式实现这个接口,Context使用这个接口调用不同的算法,一般使用接口或抽象类实现。



  ConcreteStrategy(具体策略类):



  2、 实现了Strategy定义的接口,提供具体的算法实现。



 



策略模式实战1:

package org.leiwen.dp.action.stragety.constants;
 
 
 

  import java.util.Map;
 
 
 

  //常量接口
  
 public interface ConstantProvider {
  
 

   Map<String, String> loadConfiguration();
  
 }
  
 

   
 
 
 

   package org.leiwen.dp.action.stragety.constants.impl;
 
 
 

  import java.io.File;
  
 import java.io.InputStream;
  
 import java.util.HashMap;
  
 import java.util.List;
  
 import java.util.Map;
  
 

  import org.dom4j.Document;
  
 import org.dom4j.DocumentException;
  
 import org.dom4j.Element;
  
 import org.dom4j.io.SAXReader;
  
 import org.leiwen.dp.action.stragety.constants.ConfigurationException;
  
 import org.leiwen.dp.action.stragety.constants.ConstantProvider;
  
 

   
 
 
 

  public class 
  XmlConstantProvider implements ConstantProvider {
 
 
 

   private String configFileName;
 
 
 

   private Map<String, String> config = new HashMap<String, String>();
 
 
 

   public XmlConstantProvider(String fileName) {
  
   this.configFileName = fileName;
  
  }
  
 

   public XmlConstantProvider() {
 
 
 

   }
 
 
 

   @Override
  
  public Map<String, String> loadConfiguration() {
  
 

    // 使用SAXReader解析算法
  
   SAXReader saxReader = new SAXReader();
  
   ClassLoader classLoader = this.getClass().getClassLoader();
  
   InputStream inputStream = classLoader
  
     .getResourceAsStream(configFileName);
  
 

    if (inputStream == null) {
  
    throw new ConfigurationException("intputStream == null");
  
   }
  
 

    Document doc = null;
  
   try {
  
    doc = saxReader.read(inputStream);
  
    Element root = doc.getRootElement();
  
    List<Element> elements = root.elements("constant");
  
 

     for (Element e : elements) {
  
     String name = e.attributeValue("name");
  
     String value = e.attributeValue("value");
  
     if (name != null && value != null) {
  
      config.put(name, value);
  
     }
  
    }
  
   } catch (DocumentException e) {
  
    throw new ConfigurationException(e);
  
   }
  
 

    return config;
  
  }
  
 

  }
 
 
 

   
 
 
 

  package org.leiwen.dp.action.stragety.constants.impl;
 
 
 

  import java.io.IOException;
  
 import java.io.InputStream;
  
 import java.util.HashMap;
  
 import java.util.Map;
  
 import java.util.Map.Entry;
  
 import java.util.Properties;
  
 import java.util.Set;
  
 

  import org.leiwen.dp.action.stragety.constants.ConfigurationException;
  
 import org.leiwen.dp.action.stragety.constants.ConstantProvider;
  
 

   
 
 
 

  //常量提供者的实现,读取属性文件的方式
  
 public class 
  PropertiesConstantProvider implements ConstantProvider {
  
 

   public static final String FILE_NAME = "constants.properties";
 
 
 

   private Map<String, String> context = new HashMap<String, String>();
 
 
 

   @Override
  
  public Map<String, String> loadConfiguration() {
  
   Properties props = new Properties();
  
 

    InputStream in = this.getClass().getClassLoader()
  
     .getResourceAsStream(FILE_NAME);
  
 

    try {
  
    props.load(in);
  
   } catch (IOException e) {
  
    throw new ConfigurationException(e);
  
   }
  
 

    Set<Entry<Object, Object>> entrys = props.entrySet();
  
   for (Entry<Object, Object> entry : entrys) {
  
    String name = (String) entry.getKey();
  
    String value = (String) entry.getValue();
  
    if (name != null && value != null) {
  
     context.put(name, value);
  
    }
  
   }
  
   return context;
  
  }
  
 }
  
 

  
 package org.leiwen.dp.action.stragety.constants.impl;
  
 

  import java.util.Map;
 
 
 

  import org.leiwen.dp.action.stragety.constants.ConstantProvider;
 
 
 

  //自定义常量提供器
  
 public class 
  CustomConstantProvider implements ConstantProvider {
  
 

   @Override
  
  public Map<String, String> loadConfiguration() {
  
   // 根据自己的配置格式,实现相应的算法
  
   return null;
  
  }
  
 

  }
  
 
 

   
 
 
 

  package org.leiwen.dp.action.stragety.constants;
 
 
 

  import java.util.HashMap;
  
 import java.util.List;
  
 import java.util.Map;
  
 import java.util.concurrent.CopyOnWriteArrayList;
  
 

  //常量管理器
  
 public class 
  ConstantManager {
  
 

   // 内部封装了所有的容器加载器ContainerProvider
  
  private List<ConstantProvider> providers = new CopyOnWriteArrayList<ConstantProvider>();
  
 

   // 保存所有的常量
  
  private Map<String, String> context = new HashMap<String, String>();
  
 

   // 增加常量提供器
  
  public void addConfigurationProvider(ConstantProvider provider) {
  
   providers.add(provider);
  
  }
  
 

   // 初始化过程,实际上就是将各种各样的配置元素,无论是XML形式还是Properties文件形式(甚至可能是其它自定义的配置形式)
  
  // 转化为Java对象的过程。
  
  public void init() {
  
   // 不同的ConstantProvider之间并没有依赖关系。这一点告诉我们,所有的常量加载器对于我们而言是一视同仁的。
  
   for (ConstantProvider provider : providers) {
  
    Map<String, String> map;
  
    try {
  
     map = provider.loadConfiguration();
  
     if (map != null) {
  
      context.putAll(map);
  
     }
  
    } catch (Exception e) {
  
     e.printStackTrace();
  
    }
  
 

    }
  
  }
  
 

   // 打印常量
  
  public void printConstants() {
  
   for (Map.Entry<String, String> entry : context.entrySet()) {
  
    String name = entry.getKey();
  
    String value = entry.getValue();
  
    System.out.println(name + "=" + value);
  
   }
  
  }
  
 }
  
 

   
 
 
 

  package org.leiwen.dp.action.stragety.constants;
 
 
 

  import org.dom4j.DocumentException;
 
 
 

   
 
 
 

  public class 
  ConfigurationException extends RuntimeException {
 
 
 

   public ConfigurationException() {
  
   super();
  
  }
  
 

   public ConfigurationException(String message, Throwable cause) {
  
   super(message, cause);
  
  }
  
 

   public ConfigurationException(String message) {
  
   super(message);
  
  }
  
 

   public ConfigurationException(Throwable cause) {
  
   super(cause);
  
  }
  
 

  }


2个配置文件(都位于类路径下)


constants.properties
 
 
 

     name=fans
  
    school=wust
  
 

   
 
 
 

  constants.xml
 
 
 

  <constants>
  
  <constant name="fans" value="leiwen" />
  
 

   <constant name="fanssoft" value="软林至尊,fans同盟。" />
 
 
 

  </constants>
 
 
 

   
 
 
 

  package org.leiwen.dp.action.stragety.constants;
 
 
 

  import org.leiwen.dp.action.stragety.constants.impl.PropertiesConstantProvider;
  
 import org.leiwen.dp.action.stragety.constants.impl.XmlConstantProvider;
  
 

  /**
  
  * @author 雷文 2012-3-24
  
  */
  
 public class 
  StragetyTest {
  
 

   //
  
  public static void main(String[] args) {
  
   ConstantProvider xmlProvider =  new XmlConstantProvider("constants.xml");
  
   ConstantProvider propProvider = new PropertiesConstantProvider();
  
   
  
   
  
   ConstantManager manager = new ConstantManager();
  
   manager.addConfigurationProvider(xmlProvider);
  
   manager.addConfigurationProvider(propProvider);
  
   
  
   manager.init();
  
   manager.printConstants();
  
 

   }
 
 
 

  }


程序运行结果:



 

设计模式实战13--行为型--策略模式_classloader_02

 

策略模式实战2(大话设计模式书上的例子):

package org.leiwen.dp.action.stragety.basic;
//现金收费抽象类
 public abstract class CashSuper { // 使用枚举类型表示收费类型
  public enum PayType {
   CASH_NORMAL, CASH_RETURN, CASH_REBATE
  }; // 现金收取抽象类的抽象方法,收取现金,参数为原价,返回值为当前价
  public abstract double acceptCash(double money);}
 
package org.leiwen.dp.action.stragety.basic;
 /**
  * 正常收费子类
  */
 public class CashNormal extends CashSuper { //正常收费,原价返回
  public double acceptCash(double money) {
   return money;
  }
 }         package org.leiwen.dp.action.stragety.basic;
  
 /**
  
  * 打折收费子类
  
  * @author Administrator
  
  *
  
  */
  
 public class 
  CashRebate extends CashSuper {
  
 

   private double moneyRebate = 1;
 
 
 

   //打折收费,初始化时,需要输入折扣率,如八折,就是0.8
  
  public CashRebate(double moneyRebate) {
  
   this.moneyRebate = moneyRebate;
  
  }
  
 

   public double acceptCash(double money) {
  
   return money * moneyRebate;
  
  }
  
 }
  
 

   
 
 
 

  package org.leiwen.dp.action.stragety.basic;
 
 
 

  /**
  
  * 返利收费子类 
  
  */
  
 public class 
  CashReturn extends CashSuper {
  
 

   private double moneyCondition = 0.0;
 
 
 

   private double moneyReturn = 0.0;
 
 
 

   // 返利收费,初始化时必须要输入返利条件和返利值,比如满300返100,则moneyCondition=300,moneyReturn=100
  
  public CashReturn(double moneyCondition, double moneyReturn) {
  
   this.moneyCondition = moneyCondition;
  
   this.moneyReturn = moneyReturn;
  
  }
  
 

   public double acceptCash(double money) {
  
   double result = money;
  
   //若大于返利条件,则需要减去返利值
  
   if (money >= moneyCondition) {
  
    result = money - Math.floor(money / moneyCondition) * moneyReturn;
  
   }
  
   return result;
  
  }
  
 

  }
 
 
 

   
 
 
 

  package org.leiwen.dp.action.stragety.basic;
 
 
 

  
 //策略模式实现
  
 public class 
  CashContext {
  
 

   private CashSuper cs;
 
 
 

   //通过构造方法,传入具体的收费策略
  
  public CashContext(CashSuper cs) {
  
   this.cs = cs;
  
  }
  
 

   public double getResult(double money) {
  
   //根据收费策略的不同,获得计算结果
  
   return cs.acceptCash(money);
  
  }
  
 }
  
 

   
 
 
 

   
 
 
 

  package org.leiwen.dp.action.stragety.basic;
 
 
 

  
 /**
  
  * @author 雷文 2012-2-17
  
  * @since 1.0
  
  */
  
 public class 
  StragetyTest {
  
 

   public static void main(String[] args) {
  
   // 测试策略模式的实现
  
   //CashSuper cs = CashFactory.createCashAccept(PayType.CASH_REBATE);
  
   CashSuper cs = new CashRebate(0.8);
  
   CashContext context = new CashContext(cs);
  
   double money = context.getResult(200);
  
   System.out.println("实收:" + money + "元");
  
 

   }
  
 }



有任何赞美,批评,建议,意见,欢迎留言,欢迎拍砖。(*^__^*)

举报

相关推荐

0 条评论