策略模式體現了這樣兩個原則——封裝變化和對接口編程而不是對實現編程。設計模式的作者把策略模式定義如下:
Define a family of algorithms, encapsulate each one, and make them interchangeable. [The] Strategy [pattern] lets the algorithm vary independently from clients that use it.(策略模式定義了一系列的算法,並將每一個算法封裝起來,而且使它們還可以相互替換。策略模式讓算法獨立於使用它的客戶而變化。)
策略模式將整個軟件構建爲可互換部分的鬆耦合的集合,而不是單一的緊耦合系統。鬆耦合的軟件可擴展性更好,更易於維護且重用性好。
public abstract class StrategyDiscount {
private int num;
private int price;
public StrategyDiscount(int price, int num) {
this.num = num;
this.price = price;
}
public int getNum() {
return num;
}
public int getPrice() {
return price;
}
public abstract double getDiscount();
}
三個具體實現的策略角色,分別代表無促銷、滿減促銷、打折促銷
public class NoDiscountStrategy extends StrategyDiscount {
public NoDiscountStrategy(int price,int num) {
super(num, price);
}
@Override
public double getDiscount() {
return getPrice() * getNum();
}
}
public class FixDiscountStrategy extends StrategyDiscount {
public FixDiscountStrategy(int price, int num ) {
super(num, price);
}
@Override
public double getDiscount() {
int sum = getNum() * getPrice();
if(sum > 100 ) { //滿100減20
return sum-20;
}else
return sum;
}
}
public class PercentDisCountStrategy extends StrategyDiscount {
public PercentDisCountStrategy(int price, int num) {
super(num, price);
}
@Override
public double getDiscount() {
return 0.8 * getPrice() * getNum(); //打八折
}
}
環境角色Context,屏蔽對具體策略角色的直接訪問
public class Context {
private StrategyDiscount strategyDiscount;
public Context(StrategyDiscount strategyDiscount) {
this.strategyDiscount = strategyDiscount;
}
public double contextCalDisc() {
return strategyDiscount.getDiscount();
}
}
以上關於促銷案例的策略模式就已經完成,以下是客戶端調用的類
public class Client {
public static void main(String[] args) {
Context c1 = new Context(new NoDiscountStrategy(20, 6));
System.out.println("該商品不促銷,購買總額: " + c1.contextCalDisc());
Context c2 = new Context(new FixDiscountStrategy(20, 6));
System.out.println("該商品參與滿減促銷,購買總額 : " + c2.contextCalDisc());
Context c3 = new Context(new PercentDisCountStrategy(20, 6));
System.out.println("該商品參與打八折促銷,購買總額 :" + c3.contextCalDisc());
}
}