设计模式六策略工厂注解实例应用

前景回顾:

假设我们有一个超市会员的场景,根据不同的消费额制定不同的策略,用上文的方法设计好策略后,在用户结账的时候我们可以调用:

//客户类
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) 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();
    }

你可能感兴趣的:(设计模式六策略工厂注解实例应用)