设计模式-简单工厂设计模式与策略模式之java实现二
2016-12-17 11:50
766 查看
设计模式-简单工厂设计模式与策略模式之java实现二
接上一篇博客,继续讲“商场促销”方案的实现。上一篇博客,我们采用简单工厂模式造各种“促销方案”的对象,然后,这也造成了一个不足之处:当促销方案多了之后,那这个工厂岂不是会越来越庞大,进而可能会走上相当臃肿的道路。于是乎,我们想改变这种策略,采用了策略模式;
将各种算法(这里指各种促销方案)各自进行封装,抽取出其中的接口,之后开发一个CashContext,提供getResult方法,其中该方法目的用于根据参数造对象,只不过造对象的方法不同于工厂模式。下面看看这个CashContext的代码StrategyMode.java:
package com.simpleFactoryMode;
import com.strategy.IStrategyCash;
import com.strategy.StrategyCashNormal;
import com.strategy.StrategyCashRebate;
import com.strategy.StrategyCashReturn;
/**
* 策略模式
* @author zhonglinsen
*
*/
public class StrategyMode {
private IStrategyCash strategyCash;
/**
* 获取收费实例
* @param mode 选取模式(收费的方式)
* @param money 当前本应收费
* @param rebate 打折策略的打折
* @param moneyCondition 返利策略的满额
* @param moneyReturn 返利策略的返额
* @return
* @throws Exception
*/
public StrategyMode(String mode,String money,String rebate,String moneyCondition,String moneyReturn) throws Exception {
switch (mode) {
case "1":
//正常收费
strategyCash=new StrategyCashNormal();
break;
case "2":
//打折
strategyCash=new StrategyCashRebate(Double.parseDouble(rebate));
break;
case "3":
//返利
strategyCash=new StrategyCashReturn(Double.parseDouble(moneyCondition), Double.parseDouble(moneyReturn));
break;
default:
break;
}
}
/**
* 具体的收费方法
* @param money
* @return
*/
public double getResult(double money){
return strategyCash.getResult(money);
}
}
我们设计这个类的时候,将收费的方法放在这个类中,而不是暴露在客户端了,再看看客户端的写法StrategyCodeServlet2.java:
package com.designModeServlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.sf.json.JSONObject;
import com.simpleFactoryMode.StrategyMode;
import com.util.ResponseUtil;
/**
* 策略模式
* @author zhonglinsen
*
*/
public class StrategyCodeServlet2 extends HttpServlet{
/**
*
*/
private static final long serialVersionUID = -6165004124140768399L;
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
JSONObject result=new JSONObject();
String mode=request.getParameter("mode");
String money=request.getParameter("money");
String rebate=request.getParameter("rebate");
String moneyCondition=request.getParameter("moneyCondition");
String moneyReturn=request.getParameter("moneyReturn");
StrategyMode strategyMode=null;
try {
strategyMode = new StrategyMode(mode, money, rebate, moneyCondition, moneyReturn);
} catch (Exception e1) {
e1.printStackTrace();
}
double cashResult=strategyMode.getResult(Double.parseDouble(money));
result.put("cashResult", cashResult);
try {
ResponseUtil.write(response, result);
} catch (Exception e) {
System.out.println("异常信息: "+e.getMessage());
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
doGet(req, resp);
}
}
策略模式的客户端代码,只是暴露StrategyMode这个CashContext而已:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201612/6498dcc5244ebef525f4da88c371ec8c)
而简单工厂模式的客户端代码,则暴露了接口IStrategyCash跟工厂类SimpleFactoryMode,
![](https://oscdn.geek-share.com/Uploads/Images/Content/201612/b40350fddd160f23d1ca56d8ed7a248c)
前端页面与Js代码已经在上一篇贴出来了,就不多说了!
紧接着,我们考虑到在造对象的方式上,还是免不了需要去判断是哪一种方案(switch...cash就是证明),而正如我所言,方案 如果多了,还是会使得switch..cash变得庞大。。。于是乎,我想到了结合反射。
但是,可能是还没精通反射,故而,我对类跟接口进行重新设计,并在前端设计好方案的选择,通过加载一个属性配置文件读取得知客户将调用哪一个方案类strategyProperties.properties:
StrategyCashNormal=com.strategy.reflect.StrategyCashNormal
StrategyCashRebate=com.strategy.reflect.StrategyCashRebate
StrategyCashReturn=com.strategy.reflect.StrategyCashReturn
然后,就通过这个来造对象了:
package com.simpleFactoryMode;
import java.io.FileInputStream;
import java.util.Properties;
import com.strategy.reflect.IStrategyCash;
/**
* 策略模式 + 反射
* @author zhonglinsen
*
*/
public class ReflectStrategyMode {
//加载属性配置文件,并进行读取特定的对象名称
private static Properties prop=new Properties();
public ReflectStrategyMode(String fileUrl) {
try {
prop.load(new FileInputStream(fileUrl));
} catch (Exception e) {
e.printStackTrace();
}
}
public ReflectStrategyMode() {
}
/**
* 获取结果
* @param mode
* @param money
* @param rebate
* @param moneyCondition
* @param moneyReturn
* @return
* @throws Exception
*/
public double getResult(String mode,String money,String rebate,String moneyCondition,String moneyReturn) throws Exception {
IStrategyCash strategyCash= (IStrategyCash) Class.forName(String.valueOf(prop.get(mode))).newInstance();
double finalCash=
strategyCash.getResult(stringToDouble(money), stringToDouble(rebate), stringToDouble(moneyCondition), stringToDouble(moneyReturn));
return finalCash;
}
public double stringToDouble(String param){
return Double.parseDouble(param);
}
}
而客户端类StrategyCodeServlet3.java:
package com.designModeServlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.sf.json.JSONObject;
import com.simpleFactoryMode.ReflectStrategyMode;
import com.util.ResponseUtil;
/**
* 策略模式 反射
* @author zhonglinsen
*
*/
public class StrategyCodeServlet3 extends HttpServlet{
/**
*
*/
private static final long serialVersionUID = -6165004124140768399L;
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
JSONObject result=new JSONObject();
String mode=request.getParameter("mode");
String money=request.getParameter("money");
String rebate=request.getParameter("rebate");
String moneyCondition=request.getParameter("moneyCondition");
String moneyReturn=request.getParameter("moneyReturn");
//servlet获取项目路径:得到的是一个临时路径
///E:/java_BasicWeb/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/javaDesignMode/WEB-INF/classes/com/
String rootPath=this.getClass().getResource("").getPath();
int index = rootPath.lastIndexOf("/",rootPath.lastIndexOf("/")-1) + 1;
String newPath=rootPath.substring(0,index);
String fireUrl=newPath+"configs/strategyProperties.properties";
//FileInputStream fileInputStream=new FileInputStream(fireUrl);
double finalCash=0.0;
try {
ReflectStrategyMode strategyMode=new ReflectStrategyMode(fireUrl);
finalCash=strategyMode.getResult(mode, money, rebate, moneyCondition, moneyReturn);
System.out.println(finalCash);
} catch (Exception e) {
System.out.println(e.getMessage());
}
result.put("cashResult", finalCash);
try {
ResponseUtil.write(response, result);
} catch (Exception e) {
System.out.println("异常信息: "+e.getMessage());
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
doGet(req, resp);
}
}
对于接口的设计:
package com.strategy.reflect;
public interface IStrategyCash {
double getResult(double money,double rebate,double moneyCondition,double moneyReturn);
}
正常收费:
package com.strategy.reflect;
public class StrategyCashNormal implements IStrategyCash {
@Override
public double getResult(double money, double rebate, double moneyCondition,
double moneyReturn) {
return money;
}
}
打折的:
package com.strategy.reflect;
public class StrategyCashRebate implements IStrategyCash {
@Override
public double getResult(double money, double rebate, double moneyCondition,
double moneyReturn) {
return money*rebate;
}
}
满300返100
package com.strategy.reflect;
public class StrategyCashReturn implements IStrategyCash {
@Override
public double getResult(double money, double rebate, double moneyCondition,
double moneyReturn) {
double result=money;
if (money>=moneyCondition) {
result=money-Math.floor(money/moneyCondition)*moneyReturn;
}
return result;
}
}
而前端页面的那个选项变为:
<!-- <option value="StrategyCashNormal">正常收费</option>
<option value="StrategyCashRebate">打8折</option>
<option value="StrategyCashReturn">满300送100</option> -->
跑到tomcat即可实现效果。
讲的可能不太好,可以来这里下载源码:源码下载
也可以来群与我交流:java修炼塔 535296702
接上一篇博客,继续讲“商场促销”方案的实现。上一篇博客,我们采用简单工厂模式造各种“促销方案”的对象,然后,这也造成了一个不足之处:当促销方案多了之后,那这个工厂岂不是会越来越庞大,进而可能会走上相当臃肿的道路。于是乎,我们想改变这种策略,采用了策略模式;
将各种算法(这里指各种促销方案)各自进行封装,抽取出其中的接口,之后开发一个CashContext,提供getResult方法,其中该方法目的用于根据参数造对象,只不过造对象的方法不同于工厂模式。下面看看这个CashContext的代码StrategyMode.java:
package com.simpleFactoryMode;
import com.strategy.IStrategyCash;
import com.strategy.StrategyCashNormal;
import com.strategy.StrategyCashRebate;
import com.strategy.StrategyCashReturn;
/**
* 策略模式
* @author zhonglinsen
*
*/
public class StrategyMode {
private IStrategyCash strategyCash;
/**
* 获取收费实例
* @param mode 选取模式(收费的方式)
* @param money 当前本应收费
* @param rebate 打折策略的打折
* @param moneyCondition 返利策略的满额
* @param moneyReturn 返利策略的返额
* @return
* @throws Exception
*/
public StrategyMode(String mode,String money,String rebate,String moneyCondition,String moneyReturn) throws Exception {
switch (mode) {
case "1":
//正常收费
strategyCash=new StrategyCashNormal();
break;
case "2":
//打折
strategyCash=new StrategyCashRebate(Double.parseDouble(rebate));
break;
case "3":
//返利
strategyCash=new StrategyCashReturn(Double.parseDouble(moneyCondition), Double.parseDouble(moneyReturn));
break;
default:
break;
}
}
/**
* 具体的收费方法
* @param money
* @return
*/
public double getResult(double money){
return strategyCash.getResult(money);
}
}
我们设计这个类的时候,将收费的方法放在这个类中,而不是暴露在客户端了,再看看客户端的写法StrategyCodeServlet2.java:
package com.designModeServlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.sf.json.JSONObject;
import com.simpleFactoryMode.StrategyMode;
import com.util.ResponseUtil;
/**
* 策略模式
* @author zhonglinsen
*
*/
public class StrategyCodeServlet2 extends HttpServlet{
/**
*
*/
private static final long serialVersionUID = -6165004124140768399L;
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
JSONObject result=new JSONObject();
String mode=request.getParameter("mode");
String money=request.getParameter("money");
String rebate=request.getParameter("rebate");
String moneyCondition=request.getParameter("moneyCondition");
String moneyReturn=request.getParameter("moneyReturn");
StrategyMode strategyMode=null;
try {
strategyMode = new StrategyMode(mode, money, rebate, moneyCondition, moneyReturn);
} catch (Exception e1) {
e1.printStackTrace();
}
double cashResult=strategyMode.getResult(Double.parseDouble(money));
result.put("cashResult", cashResult);
try {
ResponseUtil.write(response, result);
} catch (Exception e) {
System.out.println("异常信息: "+e.getMessage());
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
doGet(req, resp);
}
}
策略模式的客户端代码,只是暴露StrategyMode这个CashContext而已:
而简单工厂模式的客户端代码,则暴露了接口IStrategyCash跟工厂类SimpleFactoryMode,
前端页面与Js代码已经在上一篇贴出来了,就不多说了!
紧接着,我们考虑到在造对象的方式上,还是免不了需要去判断是哪一种方案(switch...cash就是证明),而正如我所言,方案 如果多了,还是会使得switch..cash变得庞大。。。于是乎,我想到了结合反射。
但是,可能是还没精通反射,故而,我对类跟接口进行重新设计,并在前端设计好方案的选择,通过加载一个属性配置文件读取得知客户将调用哪一个方案类strategyProperties.properties:
StrategyCashNormal=com.strategy.reflect.StrategyCashNormal
StrategyCashRebate=com.strategy.reflect.StrategyCashRebate
StrategyCashReturn=com.strategy.reflect.StrategyCashReturn
然后,就通过这个来造对象了:
package com.simpleFactoryMode;
import java.io.FileInputStream;
import java.util.Properties;
import com.strategy.reflect.IStrategyCash;
/**
* 策略模式 + 反射
* @author zhonglinsen
*
*/
public class ReflectStrategyMode {
//加载属性配置文件,并进行读取特定的对象名称
private static Properties prop=new Properties();
public ReflectStrategyMode(String fileUrl) {
try {
prop.load(new FileInputStream(fileUrl));
} catch (Exception e) {
e.printStackTrace();
}
}
public ReflectStrategyMode() {
}
/**
* 获取结果
* @param mode
* @param money
* @param rebate
* @param moneyCondition
* @param moneyReturn
* @return
* @throws Exception
*/
public double getResult(String mode,String money,String rebate,String moneyCondition,String moneyReturn) throws Exception {
IStrategyCash strategyCash= (IStrategyCash) Class.forName(String.valueOf(prop.get(mode))).newInstance();
double finalCash=
strategyCash.getResult(stringToDouble(money), stringToDouble(rebate), stringToDouble(moneyCondition), stringToDouble(moneyReturn));
return finalCash;
}
public double stringToDouble(String param){
return Double.parseDouble(param);
}
}
而客户端类StrategyCodeServlet3.java:
package com.designModeServlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.sf.json.JSONObject;
import com.simpleFactoryMode.ReflectStrategyMode;
import com.util.ResponseUtil;
/**
* 策略模式 反射
* @author zhonglinsen
*
*/
public class StrategyCodeServlet3 extends HttpServlet{
/**
*
*/
private static final long serialVersionUID = -6165004124140768399L;
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
JSONObject result=new JSONObject();
String mode=request.getParameter("mode");
String money=request.getParameter("money");
String rebate=request.getParameter("rebate");
String moneyCondition=request.getParameter("moneyCondition");
String moneyReturn=request.getParameter("moneyReturn");
//servlet获取项目路径:得到的是一个临时路径
///E:/java_BasicWeb/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/javaDesignMode/WEB-INF/classes/com/
String rootPath=this.getClass().getResource("").getPath();
int index = rootPath.lastIndexOf("/",rootPath.lastIndexOf("/")-1) + 1;
String newPath=rootPath.substring(0,index);
String fireUrl=newPath+"configs/strategyProperties.properties";
//FileInputStream fileInputStream=new FileInputStream(fireUrl);
double finalCash=0.0;
try {
ReflectStrategyMode strategyMode=new ReflectStrategyMode(fireUrl);
finalCash=strategyMode.getResult(mode, money, rebate, moneyCondition, moneyReturn);
System.out.println(finalCash);
} catch (Exception e) {
System.out.println(e.getMessage());
}
result.put("cashResult", finalCash);
try {
ResponseUtil.write(response, result);
} catch (Exception e) {
System.out.println("异常信息: "+e.getMessage());
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
doGet(req, resp);
}
}
对于接口的设计:
package com.strategy.reflect;
public interface IStrategyCash {
double getResult(double money,double rebate,double moneyCondition,double moneyReturn);
}
正常收费:
package com.strategy.reflect;
public class StrategyCashNormal implements IStrategyCash {
@Override
public double getResult(double money, double rebate, double moneyCondition,
double moneyReturn) {
return money;
}
}
打折的:
package com.strategy.reflect;
public class StrategyCashRebate implements IStrategyCash {
@Override
public double getResult(double money, double rebate, double moneyCondition,
double moneyReturn) {
return money*rebate;
}
}
满300返100
package com.strategy.reflect;
public class StrategyCashReturn implements IStrategyCash {
@Override
public double getResult(double money, double rebate, double moneyCondition,
double moneyReturn) {
double result=money;
if (money>=moneyCondition) {
result=money-Math.floor(money/moneyCondition)*moneyReturn;
}
return result;
}
}
而前端页面的那个选项变为:
<!-- <option value="StrategyCashNormal">正常收费</option>
<option value="StrategyCashRebate">打8折</option>
<option value="StrategyCashReturn">满300送100</option> -->
跑到tomcat即可实现效果。
讲的可能不太好,可以来这里下载源码:源码下载
也可以来群与我交流:java修炼塔 535296702
相关文章推荐
- 设计模式-简单工厂设计模式与策略模式之java实现
- 追MM与设计模式的JAVA实现-简单工厂方法
- 设计模式之—简单工厂方法(StaticFactory )-Java实现
- java简单工厂设计模式实现计算器
- 设计模式:浅析 抽象工厂、工厂方法、简单(静态)工厂 java实现
- 设计模式:浅析 抽象工厂、工厂方法、简单(静态)工厂 java实现
- 简单工厂设计模式实现商店买牙膏收费案例过渡到结合策略模式的理由全解
- Java设计模式之工厂模式的简单实现
- 设计模式学习笔记一 简单工厂策略模式实现销售策略的变更(一)
- 用JSP+Servlet+JavaBean模式实现一个简单的登录网页设计(JSP+Tomcat+MySQL)
- 设计模式 -- 简单工厂模式 -- c++实现
- java 设计模式 学习笔记(1) - 简单工厂模式
- 设计模式——简单工厂+策略模式
- java 设计模式-简单工厂
- 设计模式解读 之策略模式(参照策略模式与简单工厂模式的对比)
- 有趣的Java - 简单使用enum实现策略模式Strategy
- 设计模式之(简单工厂)(C#实现)(程杰)
- JAVA设计模式:简单工厂、工厂方法、抽象工厂之小结与区别
- java设计模式之简单工厂模式
- java 简单工厂设计模式