国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

行為型設計模式

2019-11-15 01:03:09
字體:
來源:轉載
供稿:網友
行為型設計模式

行為型設計模式概述

行為模式關注的是對象的行為。該類型的模式需要做的是對可能變化的行為進行抽象,通過封裝達到整個架構的可擴展性。這些模式所要封裝的行為,恰恰是軟件架構中最不穩定的部分,擴展的可能性也最大。將這些行為封裝起來,利用抽象的特性,就提供了擴展的可能。

實現的機制:

使用繼承機制在類間分派行為

使用對象組合而不是繼承,它描述一組對象怎樣協作完成單個對象所無法完成的任務


(一)模板方法(TEMPLATE METHOD)模式

問題提出:

通常我們會遇到這樣的一個問題:我們知道一個算法或是流程所需的關鍵步聚,并確定了這些步聚的執行順序。但是某些步聚的具體實現是未知的,或者是某些步聚的實現與具體的環境相關。

生活場景:

一個簡單的訂單處理需求:一個客戶可以在一個訂貨單中訂購多個貨物(也稱為訂貨單項目),貨物的銷售價是根據貨物的進貨價進行計算的。有些貨物可以打折的,有些是不可以打折的。每一個客戶都有一個信用額度,每張訂單的總價不能超出該客戶的信用額度。

根據上面的業務,我們可以知道處理一個訂單需要的步聚:

1. 遍歷訂貨單的訂貨單項目列表,累加所有貨物的總價格(根據訂貨單項目計算出銷售價)

2. 根據客戶號獲得客戶的信用額度

3. 把客戶號,訂單的總價格,及訂單項目列表寫入到數據庫

但是我們并不能確定怎么計算出貨物的銷售價,怎樣根據客戶號獲得客戶的信用額度及把訂單信息寫入數據庫這些方法的具體實現。

模板方法模式把我們不知道具體實現的步聚封裝成抽象方法,提供一些按正確順序調用它們的具體方法(這些具體方法統稱為模板方法),這樣構成一個抽象基類。子類通過繼承這個抽象基類去實現各個步聚的抽象方法,而工作流程卻由父類來控制。

public abstract class AbstractOrder {

public Order placeOrder(int customerId , List orderItemList){

int total = 0;

for(int i = 0; i < orderItemList.size();i++){

OrderItem orderItem = (OrderItem)orderItemList.get(i);

total += getOrderItemPRice(orderItem) * orderItem.getQuantity();

}

if(total > getSpendingLimit(customerId)){

throw new BusinessException("超出信用額度" + getSpendingLimit(customerId));

}

int orderId = saveOrder(customerId, total, orderItemList);

return new OrderImpl(orderId,total);

}

public abstract int getOrderItemPrice(OrderItem orderItem);

public abstract int getSpendingLimit(int customerId);

public abstract int saveOrder(int customerId, int total, List orderItemList);

}

把不變的行為搬到超類,去除子類中重復的代碼來體現他的優勢。當不變的和可變的行為在方法中混合在一起時,不變的行為就會在子類中重復出現,模板方法模式就是將這些不變的行為搬移到一個超類中,避免重復代碼。

這是一個很簡單的模式,卻被非常廣泛的使用。之所以簡單是因為在這個模式中僅僅使用到了繼承關系。

繼承關系由于自身的缺陷,被專家們扣上了“罪惡”的帽子。“使用委派關(聚合)系代替繼承關系”,“盡量使用接口實現而不是抽象類繼承”等等專家警告,讓我們這些菜鳥對繼承“另眼相看”。

其實,繼承還是有很多自身的優點所在。只是被大家濫用的似乎缺點更加明顯了。合理的利用繼承關系,還是能對你的系統設計起到很好的作用的。而模板方法模式就是其中的一個使用范例。


(二)策略(Strategy )模式

問題提出:

在業務當中常常出現一個問題有一組算法,在不同的情況下我們有可能使用不同的算法。我們需要找到一種靈活簡便的設計方式:將每一個算法封裝到具有共同接口的獨立的類中,從而使得它們可以相互替換。

生活場景:

向客戶報價,對于銷售部門的人來講,這是一個非常復雜的問題,對不同的客戶要報不同的價格,比如:

對普通客戶或者是新客戶報的是全價;

對老客戶報的價格,根據客戶年限,給予一定的折扣;

對大客戶報的價格,根據大客戶的累計消費金額,給予一定的折扣;

還要考慮客戶購買的數量和金額,比如:雖然是新用戶,但是一次購買的數量非常大,或者是總金額非常高,也會有一定的折扣;

還有,報價人員的職務高低,也決定了他是否有權限對價格進行一定的浮動折扣;

總之,向客戶報價是非常復雜的,不同的情況銷售人員采取不同的策略。

publicclassPrice {

/**@paramgoodsPrice商品銷售原價

*@paramcustomerType客戶類型

*@return計算出來的,應該給客戶報的價格*/

publicdoublequote(doublegoodsPrice,String customerType){

if(customerType.equals("普通客戶")){

System.out.println("對于新客戶或者是普通客戶,沒有折扣");

returngoodsPrice;

}elseif(customerType.equals("老客戶")){

System.out.println("對于老客戶,統一折扣5%");

returngoodsPrice*(1-0.05);

}elseif(customerType.equals("大客戶")){

System.out.println("對于大客戶,統一折扣10%");

returngoodsPrice*(1-0.1);

}

returngoodsPrice;

}

}

價格類包含了所有計算報價的算法,使得價格類,尤其是報價這個方法比較龐雜,難以維護。 咋辦?

publicclassPrice {

publicdoublequote(doublegoodsPrice,String customerType){

if(customerType.equals("普通客戶")){

returnthis.calcPriceForNormal(goodsPrice);

}elseif(customerType.equals("老客戶")){

returnthis.calcPriceForOld(goodsPrice);

}elseif(customerType.equals("大客戶")){

returnthis.calcPriceForLarge(goodsPrice);

}

returngoodsPrice;

}

privatedoublecalcPriceForNormal(doublegoodsPrice){&hellip;}

privatedoublecalcPriceForOld(doublegoodsPrice){…}

privatedoublecalcPriceForLarge(doublegoodsPrice){…}

}

再想想,問題還是存在,只不過從計算報價的方法挪動到價格類里面了,假如有100個或者更多這樣的計算方式,這會讓這個價格類非常龐大,難以維護。而且,維護和擴展都需要去修改已有的代碼,這是很不好的,違反了開-閉原則。

另外:經常會有這樣的需要,在不同的時候,要使用不同的計算方式。

比如:在公司周年慶的時候,所有的客戶額外增加3%的折扣;在換季促銷的時候,普通客戶是額外增加折扣2%,老客戶是額外增加折扣3%,大客戶是額外增加折扣5%。這意味著計算報價的方式會經常被修改,或者被切換。過了促銷時間,又還回到正常的價格體系上來了。而現在的價格類中計算報價的方法,是固定調用各種計算方式,這使得切換調用不同的計算方式很麻煩,每次都需要修改if-else里面的調用代碼。

用來解決上述問題的一個合理的解決方案就是策略模式。

策略模式使得算法可以在不影響到客戶端的情況下發生變化。策略模式把行為和環境分開。環境類負責維持和查詢行為類,各種算法在具體的策略類中提供。由于算法和環境獨立開來,算法的增減,修改都不會影響到環境和客戶端。

根據策略模式解決場景問題,設計如下:

public interface Baojia {public double baojia(double price);

}

public class Content {private Baojia bj;

public Content(Baojia bj) {super();this.bj = bj;}public double daZhe(double price){return bj.baojia(price);}

}

public class LaoKeHuYear3_5 implements Baojia {

@Overridepublic double baojia(double price) {return price*.75;}

}

public class NewKenHu implements Baojia {

@Overridepublic double baojia(double price) {if(price>10000){return price*(1-0.2);}return price;}

}

public class DaKeHu implements Baojia {

@Overridepublic double baojia(double price) {return price*0.5;}

}

public class Test {public static void main(String[] args) {Baojia bj = new LaoKeHuYear3_5();Content c = new Content(bj);double p = c.daZhe(1000);System.out.println(p);}

}


(三)觀察者(Observer )模式

問題提出:

在軟件系統中,我們有時需要定義一種一對多的依賴關系. 讓多個觀察者對象同時監聽某一個主題對象, 這個主題對象在狀態發生變化的時候,會通知所有的觀察者對象,使他們能夠自動更新自己。

生活場景:

網上商店中商品在名稱 價格等方面有變化,如果系統能自動通知會員,將網上商店區別傳統商店的一大特色.

代碼實現:定義主題類

public class product extends Observable{  

 private String name;  

 private float price;  

 public String getName(){

return name;

}

public void setName(String name){   

this.name=name;  

 //設置變化點  

  setChanged();  

  notifyObservers(name);

  }   

  public float getPrice(){

return price;

}   

public void setPrice(float price){  

  this.price=price;  

 //設置變化點  

  setChanged();   

notifyObservers(new Float(price));

  }

}

代碼實現:定義觀察者

public class NameObserver implements Observer{  

 private String name=null;  

 public void update(Observable obj,Object arg){   

  if (arg instanceof String){    

  name=(String)arg;  

   System.out.println("NameObserver :name changet to "+name);  

   }

  }

}

public class PriceObserver implements Observer{  

 private float price=0;  

 public void update(Observable obj,Object arg){  

   if (arg instanceof Float){   

   price=((Float)arg).floatValue();    

   System.out.println("PriceObserver :price changet to "+price);  

   }  

 }

}

public class Test {

public static void main(String args[]){

Product product=new Product();

NameObserver nameobs=new NameObserver();

PriceObserver priceobs=new PriceObserver();

//加入觀察者

product.addObserver(nameobs);

product.addObserver(priceobs);

product.setName("橘子紅了");

product.setPrice(9.22f);   

}

}


(四)命令(Command )模式

問題提出:

在軟件系統中,“行為請求者”與“行為實現者”通常呈現一種“緊耦合”。但在某些場合,比如要對行為進行“記錄、撤銷/重做、事務”等處理,這種無法抵御變化的緊耦合是不合適的。在這種情況下,如何將“行為請求者”與“行為實現者”解耦?將一組行為抽象為對象,可以實現二者之間的松耦合。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 青岛市| 屏东县| 毕节市| 曲水县| 连州市| 十堰市| 奉化市| 宁晋县| 永春县| 讷河市| 高青县| 台山市| 十堰市| 化德县| 体育| 天柱县| 来凤县| 高邑县| 勐海县| 太原市| 理塘县| 舒兰市| 永顺县| 任丘市| 青岛市| 自贡市| 清原| 从江县| 南木林县| 商河县| 和林格尔县| 同心县| 贵州省| 福鼎市| 陆河县| 高台县| 东宁县| 新密市| 嵩明县| 安仁县| 屯昌县|