策略模式(Strategy pattern)——簡單工廠&反射實現

定義

策略模式:指的是對象具備某個行爲,但是在不同的場景中,該行爲有不同的實現算法。
舉個幾個生活的例子,就是不同收入的人羣採用不同的稅率,登錄的不同方式,支付的不同方式;
在代碼我們也見過策略模式,如ArrayList的排序傳入的Comparator

    ArrayList list = new ArrayList();
    list.sort(new Comparator() {
        @Override
        public int compare(Object o1, Object o2) {
            //此處的本質就是一個策略
            return 0;
        }
    });

示例代碼場景描述

用戶可以選擇不同類型的支付方式,有支付寶支付,微信支付,京東白條支付,銀聯支付,根據用戶選擇地不同支付方法,執行不同的支付方式的代碼。

源代碼

/**
 * 支付接口
 *
 * @author Lenjor
 * @version 1.0
 * @date 2019-10-03 16:23
 */
public interface Pay {
    public void pay(Order order);
}


/**
 * 支付寶支付
 *
 * @author Lenjor
 * @version 1.0
 * @date 2019-10-03 16:22
 */
public class AliPay implements Pay {

    public void pay(Order order) {
        System.out.println("使用支付寶支付");
        System.out.println(order);
    }
}




/**
 * 京東支付
 *
 * @author Lenjor
 * @version 1.0
 * @date 2019-10-03 16:22
 */
public class JDPay implements Pay {
    public void pay(Order order) {
        System.out.println("使用京東白條支付");
        System.out.println(order);
    }
}




/**
 * 微信支付
 *
 * @author Lenjor
 * @version 1.0
 * @date 2019-10-03 16:22
 */
public class WechatPay implements Pay {
    public void pay(Order order) {
        System.out.println("使用微信支付");
        System.out.println(order);
    }
}


/**
 * 銀聯支付
 *
 * @author Lenjor
 * @version 1.0
 * @date 2019-10-03 16:23
 */
public class UnionPay implements Pay {
    public void pay(Order order) {
        System.out.println("使用銀聯支付");
        System.out.println(order);
    }
}




/**
 * 訂單類
 *
 * @author Lenjor
 * @version 1.0
 * @date 2019-10-03 16:24
 */
public class Order {
    private String orderNo;
    private double amount;
    private String product;

    public Order(double amount, String product) {
        this.amount = amount;
        this.product = product;
        this.orderNo = ("NO." + System.currentTimeMillis() + System.nanoTime()).substring(0, 32);
    }

    public String getOrderNo() {
        return orderNo;
    }

    public void setOrderNo(String orderNo) {
        this.orderNo = orderNo;
    }

    public double getAmount() {
        return amount;
    }

    public void setAmount(double amount) {
        this.amount = amount;
    }

    public String getProduct() {
        return product;
    }

    public void setProduct(String product) {
        this.product = product;
    }

    @Override
    public String toString() {
        return "[商品名: " + product + " , 價格: ¥ " + amount + " , 訂單號:" + orderNo + " ]";
    }
}



/**
 * 支付類型
 *
 * @author Lenjor
 * @version 1.0
 * @date 2019-10-03 16:35
 */
public enum PayType {
    ALI_PAY("AliPay"),
    WECHAT_PAY("WechatPay"),
    JD_PAY("JDPay"),
    UNION_PAY("UnionPay");

    private final String payType;

    private PayType(String payType) {
        this.payType = payType;
    }

    public String getPayType() {
        return this.payType;
    }
}

支付簡單工廠(switch 和反射兩種實現)

/**
 * 支付簡單工廠
 *
 * @author Lenjor
 * @version 1.0
 * @date 2019-10-03 16:34
 */
public class PayFactory {
    private Pay pay = null;

    private PayFactory(PayType payType) {
        //做法一:直接使用switch獲取到對應類型的支付對象
//        switch (payType) {
//            case ALI_PAY:
//                pay = new AliPay();
//                break;
//            case JD_PAY:
//                pay = new JDPay();
//                break;
//            case WECHAT_PAY:
//                pay = new WechatPay();
//                break;
//            case UNION_PAY:
//                pay = new WechatPay();
//                break;
//        }


        try {
            //做法二:利用反射獲取對應類型的支付對象
            Class clazz = Class.forName(this.getClass().getPackage().getName() + "." + payType.getPayType());
            pay = (Pay) clazz.newInstance();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }

    }

    public static PayFactory getInstance(PayType payType) {
        return new PayFactory(payType);
    }

    public void pay(Order order) {
        pay.pay(order);
    }
}

測試客戶端

/**
 * 測試類
 *
 * @author Lenjor
 * @version 1.0
 * @date 2019-10-03 16:21
 */
public class Client {

    public static void main(String[] args) {
        Order order = new Order(999.99, "RedMi 7 pro");
        PayFactory payFactory = PayFactory.getInstance(PayType.ALI_PAY);
        payFactory.pay(order);
    }
}

運行結果

在這裏插入圖片描述

總結

策略模式關心的是選擇不同,策略就不同,側重點是不同的選擇導致不同的策略。所以關鍵在於,把不同的算法(策略)封裝,使得不同的算法之間不會相互影響,當需要增加一種新的算法(策略)時,只需要新增一個新的策略類和一個枚舉值即可,不會影響到其他原有的策略。

設計模式從來都不會是單獨存在的,這裏除了使用到了策略模式,也使用到了簡單工廠模式,而工廠類持有一個Pay對象的引用,又有點像靜態代理的味道,只是這裏工廠類這裏沒有實現Pay接口。

發佈了20 篇原創文章 · 獲贊 3 · 訪問量 5829
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章