您的位置:首页 > 编程语言 > Java开发

设计模式-简单工厂设计模式与策略模式之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而已:



而简单工厂模式的客户端代码,则暴露了接口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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息