設計模式(三)策略模式

版權聲明:轉載必須註明本文轉自曉_晨的博客:http://blog.csdn.net/niunai112

目錄

導航

設計模式之六大設計原則
設計模式(一)單例模式
設計模式(二)工廠模式
設計模式(三)策略模式
設計模式(四)適配器模式
設計模式(五)享元模式
設計模式(六)建造者模式
設計模式(七)原型模式
設計模式(八)橋接模式
設計模式(九)外觀模式
設計模式(十)組合模式
設計模式(十一)裝飾器模式
設計模式(十二)代理模式
設計模式(十三)迭代器模式
設計模式(十四)觀察者模式
設計模式(十五)中介者模式
設計模式(十六)命令模式
設計模式(十七)狀態模式
設計模式(十八)訪問者模式
設計模式(十九)責任鏈模式
設計模式(二十)解釋器模式
設計模式(二十一)備忘錄模式
設計模式(二十二)模板模式
設計模式總結篇(爲什麼要學習設計模式,學習設計模式的好處)

前言

策略模式是一種非常常用的設計模式,而且我們日常生活中也經常會遇到,比如你到商店裏去買東西的時候,可能會根據你會員卡等級的不一樣而選擇不同的優惠方案。

而在java中,策略模式廣泛應用於代碼開發中,就拿買東西舉例子。
strategy
Normal,Vip,SuperVip是CalcPrice的實現類,用來實現具體的策略,Customer關聯Calcprice接口,通過傳入的參數,爲其選擇正確的策略

public interface CalcPrice {//定義優惠接口
    double calcPrice(double price);
}
public class Normal implements CalcPrice {
    @Override
    public double calcPrice(double price) {
        return price;//不優惠
    }
}
public class Vip implements CalcPrice {
    @Override
    public double calcPrice(double price) {
        return price * 0.9;//打9折
    }
}
public class SuperVip implements CalcPrice {
    @Override
    public double calcPrice(double price) {
        return price * 0.8;//打8折
    }
}
public class Customer {
    double totalConsume = 0;
    double currentConsume = 0;
    CalcPrice strategy;//具體使用的策略

    public double buy(double current){

        return strategy.calcPrice(current);

    }


}


public class Test {
    public static void main(String[] args) {
        Customer customer = new Customer();
        customer.setStrategy(new Normal());
        System.out.println("In Normal strategy 1000 need pay: " + customer.buy(1000));
        customer.setStrategy(new Vip());
        System.out.println("In Vip strategy 1000 need pay: " + customer.buy(1000));
        customer.setStrategy(new SuperVip());
        System.out.println("In SuperVip strategy 1000 need pay: " + customer.buy(1000));
    }
}


測試結果如下
------------------------------

In Normal strategy 1000 need pay: 1000.0
In Vip strategy 1000 need pay: 900.0
In SuperVip strategy 1000 need pay: 800.0

上面就是策略模式,當需要不同的策略的時候,就自己傳入策略實現類,然後利用策略來進行計算。

策略模式的優點
  (1)策略模式提供了管理相關的算法族的辦法。策略類的等級結構定義了一個算法或行爲族。恰當使用繼承可以把公共的代碼移到父類裏面,從而避免代碼重複。

  (2)使用策略模式可以避免使用多重條件(if-else)語句。多重條件語句不易維護,它把採取哪一種算法或採取哪一種行爲的邏輯與算法或行爲的邏輯混合在一起,統統列在一個多重條件語句裏面,比使用繼承的辦法還要原始和落後。

策略模式的缺點
  (1)客戶端必須知道所有的策略類,並自行決定使用哪一個策略類。這就意味着客戶端必須理解這些算法的區別,以便適時選擇恰當的算法類。換言之,策略模式只適用於客戶端知道算法或行爲的情況。

  (2)由於策略模式把每個具體的策略實現都單獨封裝成爲類,如果備選的策略很多的話,那麼對象的數目就會很可觀。

策略模式可以避免使用(if-else)語句是有問題的,因爲假設我們需要客戶總消費額到達2000時,就給客戶打9折,到達3000,就打8折,這樣的策略時,在程序選擇使用哪個策略的時候是一定需要進行判斷的,雖然不一定需要(if-else)來判斷,但是說策略模式可以避免使用(if-else)語句這句話是絕對有問題的,在傳入策略實現類的時候肯定進行了判斷,如果是在程序中判斷的話,那麼大概率是使用了(if-else)語句,假如沒在程序中使用,而是買東西的店員手動傳入的話,那我………………無言以對,但是店員的腦子裏肯定也用了類似(if-else)的轉換。

作爲寫程序的,肯定要減少店員的壓力,所以這部分的判斷肯定是要寫在程序中的。如下,使用的(if-else)結構,這裏依然使用策略類,減少了(if-else)代碼塊中的代碼,使程序邏輯清晰。

public class Customer {
    double totalConsume = 0;
    double currentConsume = 0;
    CalcPrice strategy;//具體使用的策略

    public double buy(double current){

        totalConsume += current;//總消費累加
        currentConsume = current;//當前消費的金額

        if (totalConsume >= 3000){//總消費超過3000,使用SuperVip策略
            strategy = new SuperVip();
        } else if (totalConsume >= 2000){//總消費超過2000,使用Vip策略
            strategy = new Vip();
        } else {//否則,使用Normal策略
            strategy = new Normal();
        }
        return strategy.calcPrice(current);

    }


}


public class Test {
    public static void main(String[] args) {
        Customer customer = new Customer();
        System.out.println("1000 need pay" + customer.buy(1000));
        System.out.println("Strategy:" + customer.strategy);
        System.out.println("1000 need pay" + customer.buy(1000));
        System.out.println("Strategy:" + customer.strategy);
        System.out.println("1000 need pay" + customer.buy(1000));
        System.out.println("Strategy:" + customer.strategy);
    }
}

---------------

1000 need pay1000.0
Strategy:Strategy.simple.Normal@1540e19d
1000 need pay900.0
Strategy:Strategy.simple.Vip@677327b6
1000 need pay800.0
Strategy:Strategy.simple.SuperVip@14ae5a5

當總消費未滿2000不優惠,滿2000打9折,滿3000打8折。這樣一個簡單的策略模式就使用好了,當要加策略的時候就新建一個類實現CalcPrice接口,在Customer里加一個if else 的分支即可。

if else的分支是可以用註解(Annotation)的方法來解決的,之後在總結的時候我會把這個問題補上,讓策略模式的耦合度更低,代碼更加容易維護。
  
  
  

Git地址

本篇實例Github地址:https://github.com/stackisok/Design-Pattern/tree/master/src/Strategy

回到最上方


有什麼不懂或者不對的地方,歡迎留言。
喜歡LZ文章的小夥伴們,可以關注一波,也可以留言,LZ會回你們的。
覺得寫得不錯的小夥伴,歡迎轉載,但請附上原文地址,謝謝^_^!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章