文档章节

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

jtn
 jtn
发布于 2015/04/13 15:09
字数 1259
阅读 3
收藏 0
策略模式(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 + "元");
 }
}
 
有任何赞美,批评,建议,意见,欢迎留言,欢迎拍砖。(*^__^*)

© 著作权归作者所有

jtn

jtn

粉丝 12
博文 879
码字总数 879609
作品 0
武汉
程序员
私信 提问
JavaScript设计模式总结

之前看过《JavaScript设计模式与开发实践》这本书,对书中的设计模式和一些相关案例也有了一定的了解,同时把这些设计模式的应用对应在在一些其他的项目中,进行了一些整理,如下仅供参考: ...

jefferyE
03/26
0
0
PHP设计模式(一):简介及创建型模式

我们分三篇文章来总结一下设计模式在PHP中的应用,这是第一篇创建型模式。 一、设计模式简介 首先我们来认识一下什么是设计模式: 设计模式是一套被反复使用、容易被他人理解的、可靠的代码设...

juhenj
2014/05/15
280
2
设计模式Java Design Pattern-工厂方法模式FactoryMethod

我的博客 一、 设计模式的分类 大体可以分为三类: 创建型模式(5个) 单例模式、原型模式、工厂方法模式、抽象工厂模式、建造者模式 结构性模式(7个) 适配器模式、装饰器模式、代理模式、...

勇敢写信
2018/03/22
0
0
JavaScript 的一些设计模式

设计模式的定义:在面向对象软件设计过程中针对特定问题的简洁而优雅的解决方案 设计模式是前人解决某个特定场景下对而总结出来的一些解决方案。可能刚开始接触编程还没有什么经验的时候,会...

格西南
08/20
0
0
EasyToLearnDesignPattern

简单上手设计模式 GITHUB:https://github.com/Fisher-Joe/EasyToLearnDesignPattern 本文旨在使用最简单的语言,最简单的代码让人学习设计模式(最起码是我) 说明: 本文的所有内容都是基于...

芝麻开门
04/19
0
0

没有更多内容

加载失败,请刷新页面

加载更多

如何编写高质量的 JS 函数(1) -- 敲山震虎篇

本文首发于 vivo互联网技术 微信公众号 链接:https://mp.weixin.qq.com/s/7lCK9cHmunvYlbm7Xi7JxQ 作者:杨昆 一千个读者,有一千个哈姆雷特。 此系列文章将会从函数的执行机制、鲁棒性、函...

vivo互联网技术
45分钟前
5
0
学会这5个Excel技巧,让你拒绝加班

在网上,随处都可以看到Excel技巧,估计已看腻了吧?但下面5个Excel技巧会让你相见恨晚。关键的是它们个个还很实用 图一 技巧1:快速删除边框 有时当我们处理数据需要去掉边框,按Ctrl+Shif...

干货趣分享
今天
11
0
JS基础-该如何理解原型、原型链?

JS的原型、原型链一直是比较难理解的内容,不少初学者甚至有一定经验的老鸟都不一定能完全说清楚,更多的"很可能"是一知半解,而这部分内容又是JS的核心内容,想要技术进阶的话肯定不能对这个...

OBKoro1
今天
9
0
高防CDN的出现是为了解决网站的哪些问题?

高防CDN是为了更好的服务网络而出现的,是通过高防DNS来实现的。高防CDN是通过智能化的系统判断来路,再反馈给用户,可以减轻用户使用过程的复杂程度。通过智能DNS解析,能让网站访问者连接到...

云漫网络Ruan
今天
15
0
OSChina 周一乱弹 —— 熟悉的味道,难道这就是恋爱的感觉

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @xiaoshiyue :好久没分享歌了分享张碧晨的单曲《今后我与自己流浪》 《今后我与自己流浪》- 张碧晨 手机党少年们想听歌,请使劲儿戳(这里)...

小小编辑
今天
3.3K
25

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部