1. 程式人生 > >Java封裝商場打折策略(Strategy模式)

Java封裝商場打折策略(Strategy模式)

有了OO的基礎後,開始認真學習設計模式。

首先學習的是Strategy,下面就封裝商場打折策略來分析下策略模式是怎樣一回事。

商場每逢節假日都會對不同的商品採用不同的打折策略,首先賣蘋果的說我的蘋果要打折,好的,我們建立Market和Apple類。

 1 /**
 2  * 
 3  * @author LingJian
 4  *
 5  */
 6 public class Market {
 7 
 8     /**
 9      * 只對Apple
10      * @param apple
11      */
12     public static void normalSell(Apple apple) {
13 System.out.println("未打折價錢:" + apple.getPrice() * apple.getWeight()); 14 } 15 /** 16 * 只對Apple 17 * @param apple 18 */ 19 public static void discountSell(Apple apple) { 20 double weight = apple.getWeight(); 21 //打折演算法 22 if(weight < 10) { 23 normalSell(apple);
24 }else if(weight >= 10 && weight < 50) { 25 System.out.println("打八八折價錢:" + apple.getPrice() * apple.getWeight() * 0.88 ); 26 }else if(weight >= 50) { 27 System.out.println("打五折價錢:" + apple.getPrice() * apple.getWeight() * 0.5 ); 28 }
29 } 30 }
 1 /**
 2  * 
 3  * @author LingJian
 4  *
 5  */
 6 public class Apple {
 7     //重量
 8     private double weight;
 9     //單價 實際開發中 涉及金錢等精確計算都是用BigDecimal
10     private double price;
11         
12     public double getWeight() {
13         return weight;
4     }
15     public void setWeight(double weight) {
16         this.weight = weight;
17     }
18     public double getPrice() {
19         return price;
20     }
21     public void setPrice(double price) {
22         this.price = price;
23     }
24     public Apple(double weight, double price) {
25         super();
26         this.weight = weight;
27         this.price = price;
28     }
29 
30 
31     
32 }
/**
 * 
 * @author LingJian
 *
 */
public class Test {

    /**
     * @param args
     */
    public static void main(String[] args) {
        //只能對蘋果打折 還不能對通用的一類事物打折 而且都是要賣什麼就寫什麼打折演算法 其實每類事物打折演算法又是不一致的
        Apple apple = new Apple(10.35, 3.6);
        Market.normalSell(apple);
        Market.discountSell(apple);
    }

}

節假日過了兩天後,賣香蕉的一看,蘋果打折促銷後,原先買香蕉的都跑去買蘋果了,不行,香蕉也要打折,不然賣不出去就爛了,OK,這個時候,我們再往Market加一個賣香蕉的打折方法和Banana類,問題很好的解決了….後來,賣梨賣橙子賣橘子的都來了,但是由於每個商品打折的演算法和策略都不一樣,咱們只能先往Market不停的加方法….顯然這不是很好的設計,不停的寫打折方法就說明我們這個打折方法不夠通用,擴充套件性不強,那這個時候怎麼辦呢?對,肯定是想辦法讓咱們的打折方法通用,增強擴充套件性,那麼說到擴充套件我們肯定得想到OO的核心-多型。

這裡,我們建立一個Discountable介面,讓需要打折的商品都實現這個介面,並且在重寫打折方法,這樣對於Market來說,我們就把具體的打折實現方式都交給了具體的物件本身來實現,我們就不用擔心演算法策略不同而不停的增加方法。

/**
 * 
 * @author LingJian
 *
 */
public class Market {



    /**
     * 對可打折的一類事物進行打折
     * @param apple
     */
    public static void discountSell(Discountable d) {
        d.discountSell();
    }
    
    
}
public class Apple implements Discountable {
    //重量
    private double weight;
    //單價 實際開發中 涉及金錢等精確計算都是用BigDecimal
    private double price;
        
    public double getWeight() {
        return weight;
    }
    public void setWeight(double weight) {
        this.weight = weight;
    }
    public double getPrice() {
        return price;
    }
    public void setPrice(double price) {
        this.price = price;
    }
    public Apple(double weight, double price) {
        super();
        this.weight = weight;
        this.price = price;
    }
    
    @Override
    public void discountSell() {
        //打折演算法
        if(weight < 10) {
            System.out.println("Apple未打折價錢:" + weight * price);
        }else if(weight >= 10 && weight < 50) {
            System.out.println("Apple打八八折價錢:" + weight * price * 0.88 );
        }else if(weight >= 50) {
            System.out.println("Apple打五折價錢:" + weight * price * 0.5 );
        }
    }
    
    
}
/**
 * 
 * @author LingJian
 *
 */
public class Banana implements Discountable {
    //重量
    private double weight;
    //單價 實際開發中 涉及金錢等精確計算都是用BigDecimal
    private double price;
    
    public double getWeight() {
        return weight;
    }
    public void setWeight(double weight) {
        this.weight = weight;
    }
    public double getPrice() {
        return price;
    }
    public void setPrice(double price) {
        this.price = price;
    }
    public Banana(double weight, double price) {
        super();
        this.weight = weight;
        this.price = price;
    }
    
    @Override
    public void discountSell() {
        //打折演算法
        if(weight < 5) {
            System.out.println("Banana未打折價錢:" + weight * price);
        }else if(weight >= 5 && weight < 10) {
            System.out.println("Banana打八八折價錢:" + weight * price * 0.88 );
        }else if(weight >= 10) {
            System.out.println("Banana打五折價錢:" + weight * price * 0.5 );
        }        
    }

}
/**
 * 
 * @author LingJian
 *
 */
public interface Discountable {
    public void discountSell();
}
/**
 * 
 * @author LingJian
 *
 */
public class Test {

    /**
     * @param args
     */
    public static void main(String[] args) {
        //可對打折一類事物進行打折啦 先是Apple
        Discountable d = new Apple(10.35, 3.6);
//        Discountable d = new Banana(10.35, 1.6);
        Market.discountSell(d);
    }

}

OK,這一次咱們採用的都是固定的按購買量打折,但是打折的策略演算法是有可能變化的,不一定每次節假日都是按購買量打折,所以咱們的打折策略不能寫死了,得能夠靈活的變化,怎麼辦呢?當然,還是多型,我們再建立一個Discountor介面,而具體的打折策略都交給具體的實現類來實現,再在需要打折的商品類中,讓其持有Discountor介面的實現子類,這樣不管每次打折策略怎麼變化,我們只需要讓打折商品持有不同的實現物件即可靈活的應對變化,這就是策略(Strategy)模式。

/**
 * 
 * @author LingJian
 *
 */
public class Apple implements Discountable {
    //重量
    private double weight;
    //單價 實際開發中 涉及金錢等精確計算都是用BigDecimal
    private double price;
    //按購買量打折
//    private Discountor d = new AppleWeightDiscountor();
    //按購買總價打折
    private Discountor d = new ApplePriceDiscountor();
    
    public double getWeight() {
        return weight;
    }
    public void setWeight(double weight) {
        this.weight = weight;
    }
    public double getPrice() {
        return price;
    }
    public void setPrice(double price) {
        this.price = price;
    }
    public Apple(double weight, double price) {
        super();
        this.weight = weight;
        this.price = price;
    }
    
    @Override
    public void discountSell() {
        d.discount(this);
    }
    
    
}
/**
 * 
 * @author LingJian
 *
 */
public interface Discountor {
    public void discount(Discountable d);
}
/**
 * 
 * @author LingJian
 *
 */
public class AppleWeightDiscountor implements Discountor {

    /**
     * 按購買量打折
     */
    @Override
    public void discount(Discountable d) {
        Apple apple = (Apple)d;
        if(apple.getWeight() < 10) {
            System.out.println("Apple未打折價錢:" + apple.getWeight() * apple.getPrice());
        }else if(apple.getWeight() >= 10 && apple.getWeight() < 50) {
            System.out.println("Apple打八八折價錢:" + apple.getWeight() * apple.getPrice() * 0.88 );
        }else if(apple.getWeight() >= 50) {
            System.out.println("Apple打五折價錢:" + apple.getWeight() * apple.getPrice() * 0.5 );
        }        
    }

}
/**
 * 
 * @author LingJian
 *
 */
public class ApplePriceDiscountor implements Discountor {

    /**
     * 購買滿10元立減1角
     * 購買滿20元立減1元
     * 購買滿30元立減5元
     */
    @Override
    public void discount(Discountable d) {
        Apple apple = (Apple)d;
        if(apple.getWeight() * apple.getPrice() < 10) {
            System.out.println("Apple未打折價錢:" + apple.getWeight() * apple.getPrice());
        }else if(apple.getWeight() * apple.getPrice() >= 10 && apple.getWeight() * apple.getPrice() < 20) {
            System.out.println("Apple購買滿10元立減1角:" + (apple.getWeight() * apple.getPrice() - 0.1) );
        }else if(apple.getWeight() * apple.getPrice() >= 20 && apple.getWeight() * apple.getPrice() < 30) {
            System.out.println("Apple購買滿20元立減1元:" + (apple.getWeight() * apple.getPrice() - 1) );
        }else if(apple.getWeight() * apple.getPrice() >= 30) {
            System.out.println("Apple購買滿30元立減5元:" + (apple.getWeight() * apple.getPrice() - 5) );
        }        
    }

}

Test類無需改變。

簡單的描繪下封裝商場打折策略的設計圖。如下所示:

                       

Market負責給Discountable的商品打折,而具體的可打折的商品的打折的演算法則交給Discountor的實現子類來具體實現。