前景回顾:
假设我们有一个超市会员的场景,根据不同的消费额制定不同的策略,用上文的方法设计好策略后,在用户结账的时候我们可以调用:
//客户类
public class Customer {
private Double totalAmount = 0D;//客户在本商店消费的总额
private Double amount = 0D;//客户单次消费金额
private CalPrice calPrice = new Common();//每个客户都有一个计算价格的策略,初始都是普通计算,即原价
//客户购买商品,就会增加它的总额
public void buy(Double amount){
this.amount = amount;
totalAmount += amount;
if (totalAmount > 3000) {//3000则改为金牌会员计算方式
calPrice = new GoldVip();
}else if (totalAmount > 2000) {//类似
calPrice = new SuperVip();
}else if (totalAmount > 1000) {//类似
calPrice = new Vip();
}
}
//计算客户最终要付的钱
public Double calLastAmount(){
return calPrice.calPrice(amount);
}
}
客户的调用于策略的实现是紧耦合的,真实场景下,我们的用户无需关心策略的具体实现,所有的策略选择都是在收银端进行的,所以我们必须把这一部分责任分离。我们可以采用简单工厂模式稍加改进,该工厂则负责策略选择,用户只需知道最后付款多少即可:
//我们使用一个标准的简单工厂来改进一下策略模式
public class CalPriceFactory {
private CalPriceFactory(){}
//根据客户的总金额产生相应的策略
public static CalPrice createCalPrice(Customer customer){
if (customer.getTotalAmount() > 3000) {//3000则改为金牌会员计算方式
return new GoldVip();
}else if (customer.getTotalAmount() > 2000) {//类似
return new SuperVip();
}else if (customer.getTotalAmount() > 1000) {//类似
return new Vip();
}else {
return new Common();
}
}
}
相应的我们用户计算消费依赖于抽象的策略接口:客户不再依赖于具体的收费策略,依赖于抽象永远是正确的。
//客户类
public class Customer {
private Double totalAmount = 0D;//客户在本商店消费的总额
private Double amount = 0D;//客户单次消费金额
private CalPrice calPrice = new Common();//每个客户都有一个计算价格的策略,初始都是普通计算,即原价
//客户购买商品,就会增加它的总额
public void buy(Double amount){
this.amount = amount;
totalAmount += amount;
/* 变化点,我们将策略的制定转移给了策略工厂,将这部分责任分离出去 */
calPrice = CalPriceFactory.createCalPrice(this);
}
//计算客户最终要付的钱
public Double calLastAmount(){
return calPrice.calPrice(amount);
}
public Double getTotalAmount() {
return totalAmount;
}
public Double getAmount() {
return amount;
}
}
使用注解,灵活扩展策略:
/**
* Created on 2017/3/23.
* Desc:策略接口
* Author:Eric.w
*/
public interface CalPrice {
Double calPrice(Double originalPrice);
}
/**
* Created on 2017/3/24.
* Desc:策略类的注解接口
* Author:Eric.w
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Inherited
public @interface CalPriceA {
public int max() default Integer.MAX_VALUE;
public int min() default Integer.MIN_VALUE;
}
/**
* Created on 2017/3/23.
* Desc:普通会员
* Author:Eric.w
*/
@CalPriceA(max = 400, min = 0)
public class Common implements CalPrice {
public Double calPrice(Double originalPrice) {
return originalPrice;
}
}
/**
* Created on 2017/3/23.
* Desc:金牌会员
* Author:Eric.w
*/
@CalPriceA(min = 400,max = 900)
public class GoldVip implements CalPrice{
public Double calPrice(Double originalPrice) {
return originalPrice * 0.5;
}
}
package com.example.patternproxy.strategy.strabutknife;
/**
* Created on 2017/3/24.
* Desc:简单工厂,用于生成不同的策略实现类
* Author:Eric.w
*/
public class KnifeCalPriceFactory {
private static final String CAL_PRICE_PACKAGE = "com.example.patternproxy.strategy.strabutknife";//这里是一个常量,表示我们扫描策略的包,这是LZ的包名
//单例
public static KnifeCalPriceFactory getInstance() {
return KnifeCalPriceFactoryInstance.instance;
}
private static class KnifeCalPriceFactoryInstance {
private static KnifeCalPriceFactory instance = new KnifeCalPriceFactory();
}
//主动获取所有的策略
private List> classList;
public KnifeCalPriceFactory init(Context context) {
classList = new ArrayList<>();
List list = getClassName("com.example.patternproxy.strategy.strabutknife", context);
// for (int i = 0; i < list.size(); i++) {
// try {
// CalPriceA priceA = Class.forName(list.get(i)).getAnnotation(CalPriceA.class);
// if (priceA != null) {
// classList.add((Class extends CalPrice>) Class.forName(list.get(i)));
// }
// } catch (ClassNotFoundException e) {
// e.printStackTrace();
// }
// }
classList.add(com.example.patternproxy.strategy.strabutknife.Common.class);
classList.add(com.example.patternproxy.strategy.strabutknife.GoldVip.class);
classList.add(com.example.patternproxy.strategy.strabutknife.SuperVip.class);
return this;
}
//返回具体的策略
public CalPrice calRealPrice(Customer customer) {
CalPrice calPrice = new Common();
for (int i = 0; i < classList.size(); i++) {
//取得注解的值
CalPriceA priceA = classList.get(i).getAnnotation(CalPriceA.class);
if (priceA != null) {
if (customer.getTotalAmount() > priceA.min() &&
customer.getTotalAmount() < priceA.max()) {
try {
calPrice = classList.get(i).newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
return calPrice;
// return null;
}
public List getClassName(String packageName, Context context) {
List classNameList = new ArrayList();
try {
DexFile df = new DexFile(context.getPackageCodePath());//通过DexFile查找当前的APK中可执行文件
Enumeration enumeration = df.entries();//获取df中的元素 这里包含了所有可执行的类名 该类名包含了包名+类名的方式
while (enumeration.hasMoreElements()) {//遍历
String className = (String) enumeration.nextElement();
if (className.contains(packageName)) {//在当前所有可执行的类里面查找包含有该包名的所有类
classNameList.add(className);
}
}
} catch (IOException e) {
e.printStackTrace();
}
return classNameList;
}
}
package com.example.patternproxy.strategy;
import android.content.Context;
import android.util.Log;
import com.example.patternproxy.strategy.stra.CalPrice;
import com.example.patternproxy.strategy.stra.Common;
import com.example.patternproxy.strategy.stra.GoldVip;
import com.example.patternproxy.strategy.stra.SuperVip;
import com.example.patternproxy.strategy.stra.Vip;
import com.example.patternproxy.strategy.strabutknife.KnifeCalPriceFactory;
//客户类
public class Customer {
private Context context;
public Customer(Context context) {
this.context = context;
}
public Customer() {
}
private Double totalAmount = 0D;//客户在本商店消费的总额
private Double amount = 0D;//客户单次消费金额
private CalPrice calPrice = new Common();//每个客户都有一个计算价格的策略,初始都是普通计算,即原价
public Double getTotalAmount() {
return totalAmount;
}
//客户购买商品,就会增加它的总额
public Customer buy(Double amount) {
this.amount = amount;
totalAmount += amount;
if (totalAmount > 3000) {//3000则改为金牌会员计算方式
calPrice = new GoldVip();
} else if (totalAmount > 2000) {//类似
calPrice = new SuperVip();
} else if (totalAmount > 1000) {//类似
calPrice = new Vip();
}
return this;
}
public Customer buyFac(Double amount) {
this.amount = amount;
totalAmount += amount;
this.calPrice = CalPriceFactory.createCalPrice(this);
return this;
}
//计算客户最终要付的钱
public Double calLastAmount() {
double fee = calPrice.calPrice(amount);
Log.e("lzy", "total customer:" + fee + "元");
return fee;
}
//计算客户最终要付的钱
public Double calLastAmountByButter() {
double fee = KnifeCalPriceFactory.getInstance().init(context)
.calRealPrice(this).calPrice(amount);
Log.e("lzy", "total customer:" + fee + "元");
return fee;
}
}
/**
* 测试类
*/
private void testButterStrategy() {
Customer customer1 = new Customer(this);
customer1.buyFac(500.0).calLastAmountByButter();
customer1.buyFac(500.0).calLastAmountByButter();
customer1.buyFac(500.0).calLastAmountByButter();
customer1.buyFac(500.0).calLastAmountByButter();
}