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

策略模式(Strategy)定义:策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。
策略模式让算法独立于使用它的客户而独立变化。
 
策略模式结构图:

 

图片

 

    
 
策略模式解析:
      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();
 }
}
 
 
程序运行结果

 

图片

 

策略模式实战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
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值