java 策略模式+简单工厂模式+反射

一、场景:在实际的项目开发中,我们常常会遇到这样的问题,实现一个功能有多重方法或策略。

比如商场中计算价格的方法:

1、商场中没有活动,那么收费就是原价;

2、商场中有活动,打8折;

3、商场中有活动,满300件100;

这三个中计算价格的方法就是三种策略。我们在不适用设计模式的情况下,就只能用if...else...获取switch..case..来判断使用哪一中计算方法,如下代码块:

/**
* 增加打折功能,在客户端增加一个折扣下拉选,打8折、7折、5折
 * @param price 单价
 * @param count 数量
 * @param discount 折扣
 * @return
 */
public Double calculation2(Double price,Double count,String discount){
	Double result=0D;
	if(price==null || count==null){
		return result;
	}
	switch (discount) {
	    case "打8折":
		result=price*count*0.8;
		break;
	    case "打7折":
		result=price*count*0.7;
		break;
	    case "打5折":
		result=price*count*0.5;
		break;
	    default:
		result=price*count;
		break;
	    }
	    return result;
}

这样写可以实现搞活动的功能,但是这样写代码属于硬编码,如果商场中不搞活动了或者新增加了一种活动规则,我们就需要重写代码,扩展性不好,因此考虑使用策略模式。

二、策略模式

2.1 定义

策略模式(Strategy)定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户。

2.2 结构


2.3 商场搞活动代码实现

(1)、抽象算法类,抽象出了计算价格的算法。

abstract class CushSuper {
	public abstract double attachMoney(double money);
}

(2)、具体算法1,正常收费

public class CushNormal extends CushSuper{
	@Override
	public double attachMoney(double money) {
		return money;
	}
}

(3)、具体算法2,打折收费

public class CushRebate extends CushSuper{

	private double cushRebate=1d;
	public CushRebate(String moneyRebate) {
		this.cushRebate=Double.parseDouble(moneyRebate);
	}
	
	/*
	 * <p>折扣收费 </p>   
	 * @param money
	 * @return  
	 */
	@Override
	public double attachMoney(double money) {
		double result=money*cushRebate;
		return result;
	}

}

(4)、具体算法3,满减收费

public class CushReturn extends CushSuper{
	
	private double cushContidion=0d;
	private double cushReturn=0;
	public CushReturn(String cushContidion,String cushReturn) {
		this.cushContidion=Double.parseDouble(cushContidion);
		this.cushReturn=Double.parseDouble(cushReturn);
	}
	
	/*
	 * <p>满减收费 </p>   
	 * @param money
	 * @return   
	 */
	@Override
	public double attachMoney(double money) {
		double result=money-Math.floor(money/cushContidion)*cushReturn;
		return result;
	}

}

(5)、context上下文,维护一个对Strategy对象的引用。

public class CushContxt {

	private CushSuper cushSuper;
	public CushContxt(CushSuper cushSuper) {
		this.cushSuper=cushSuper;
	}
	
	public double getResult(double money){
		return cushSuper.attachMoney(money);
	}
}

(6)、客户端使用

public class Test {
	public static void main(String[] args) {
		double price=10d;
		double count=3d;
		
		//计算总价
		Double money=price*count;
		//获取输入框中的类型
//		String type="正常收费";
		String type="打8折";
//		String type="打5折";
//		String type="满300减100";
		CushContxt content=null;
		switch (type) {
		case "正常收费":
			content=new CushContxt(new CushNormal());
			break;
		case "打8折":
			content=new CushContxt(new CushRebate("0.8"));
			break;
		case "打5折":
			content=new CushContxt(new CushRebate("0.5"));
			break;
		case "满300减100":
			content=new CushContxt(new CushReturn("300","100"));
			break;
		}
		if(content!=null){
			System.out.println(content.getResult(money));
		}	
	}
}

至此,策略模式的解释已经结束,可以看出以上代码的优缺点:

优点:1、算法可以自由切换。 2、避免使用多重条件判断。 3、扩展性好。

缺点:1、客户端必须知道所有的策略类,并自己决定由那个策略类。   2、策略类会很多。

解决这个缺点方法:策略+简单工厂

三、策略+简单工厂

为了解决客户端必须知道所有的策略类,并自己决定由那个策略类这个缺点,可以使用策略+工厂模式。

改进CushContext类如下:

public class CushContext {
	
	CushSuper cushSuper=null;
	public CushContext(String type) {
		switch (type) {
		case "正常收费":
			cushSuper=new CushNormal();
			break;
		case "打8折":
			cushSuper=new CushRebate("0.8");
			break;
		case "打5折":
			cushSuper=new CushRebate("0.5");
			break;
		case "满300减100":
			cushSuper=new CushReturn("300","100");
			break;	
		}
	}
	
	public double getResult(double money){
		return cushSuper.attachMoney(money);
	}
}

客户端改为:

public class Test {
	//使用策略模式+简单工厂模式实现
	public static void main(String[] args) {
		double price=10d;
		double count=3d;
		
		//计算总价
		Double money=price*count;
		//获取输入框中的类型
		String type1="正常收费";
		String type2="打8折";
		String type3="打5折";
		String type4="满300减100";
		CushContext content=new CushContext(type1);
		//正常收费
		System.out.println(content.getResult(money));
		//打8折
		CushContext content2=new CushContext(type2);
		System.out.println(content2.getResult(money));
		//打5折
		CushContext content3=new CushContext(type3);
		System.out.println(content3.getResult(money));
		//满300减100
		CushContext content4=new CushContext(type4);
		System.out.println(content4.getResult(money));
		
	}
}

优点:解决了需要在客户端判断使用那个实现的缺点;

缺点:在cashContext中用到了swith,也就是说,如果我们需要增加一种算法,比如"满200减50",就必须更改cashContext中的switch代码。

解决方法:策略+简单工厂+反射

四、策略+简单工厂+反射

改进CushContext类如下:

public class CushContext {
	
	 private static final String[] CUSH_CLASS_NAME = {  
        "main.java.celue.celue5.CushNormal",  
        "main.java.celue.celue5.CushRebate",  
        "main.java.celue.celue5.CushReturn"
    }; 
	
	CushSuper cushSuper=null;
	public CushContext(String type,Class[] paramsType, Object[] parmas) {
		int type2=Integer.parseInt(type);
		try {
			Class<?> clazz=Class.forName(CUSH_CLASS_NAME[type2]);
			Constructor<?> constructor=clazz.getConstructor(paramsType);
			this.cushSuper=(CushSuper)constructor.newInstance(parmas);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
	}
	
	public double getResult(double money){
		return cushSuper.attachMoney(money);
	}
}

客户端改进:

public class Test {
	public static void main(String[] args) {
		double price=100d;
		double count=3d;
		//计算总价
		Double money=price*count;
		
		//正常收费
		Class[] paramTypes = {}; 
		Object[] params = {}; 
		CushContext context=new CushContext("0",paramTypes,params);
		System.out.println(context.getResult(money));
		//打8折
		Class[] paramTypes2 = {String.class}; 
		Object[] params2 = {"0.8"}; 
		CushContext context2=new CushContext("1",paramTypes2,params2);
		System.out.println(context2.getResult(money));
		//打5折
		Class[] paramTypes3 = {String.class}; 
		Object[] params3 = {"0.5"}; 
		CushContext context3=new CushContext("1",paramTypes3,params3);
		System.out.println(context3.getResult(money));
		//满300减100
		Class[] paramTypes4 = {String.class,String.class}; 
		Object[] params4 = {"300","100"}; 
		CushContext context4=new CushContext("2",paramTypes4,params4);
		System.out.println(context4.getResult(money));
	}
}
以上就是策略模式的应用,由于本人是自己学习总结的,如果有写的不对的地方,欢迎各位大神批评指出。

猜你喜欢

转载自blog.csdn.net/qq_33157666/article/details/80399234