成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

如何在代碼中應用設計模式?

開發 前端
因為我們的項目的需求是永遠在變的,為了應對這種變化,使得我們的代碼能夠輕易的實現解耦和拓展。如果能夠保證代碼一次寫好以后都不會再改變了,那可以想怎么寫怎么寫了。

 為什么要使用設計模式

因為我們的項目的需求是永遠在變的,為了應對這種變化,使得我們的代碼能夠輕易的實現解耦和拓展。如果能夠保證代碼一次寫好以后都不會再改變了,那可以想怎么寫怎么寫了。

[[320551]]

如何判斷那里需要使用設計模式

 

在我們實現中,有一些代碼是一次寫好后續基本不會改變的,或者不太需要擴展的,比如一些工具類等。有一部分是會經常變得,設計模式大多都應用在需求會變化的這一部分。分析這些代碼會如何變,選擇合適的設計模式來優化這部分代碼。

以促銷活動需求為例

需求

為了促進商品的銷售,各大電商品臺會在平時或者一些節日的時候退出一些促銷活動刺激用戶消費,活動的類型可能會各不相同,如下:

  • 滿減,滿400減20
  • 代金卷,瑪莎拉蒂5元代金卷
  • 折扣,9折,8折
  • 每滿減,每滿200減10
  • 等等

其中有些可以疊加,有些只能單獨使用。

簡單實現

上面的需求看起來還是比較簡單的,但是如果考慮到我們是不可能一次定義好所有的促銷活動類型,后續我們可能會隨時都添加新的類型,要保證能夠簡單的實現功能擴展,那就比較麻煩了。Spring 框架用到的 9 個設計模式匯總,這個你知道嗎?

先拿到需求的時候,也不用去想那么多,挽起袖子就是一通操作:

 

  1. public class OrderPromotion {   
  2.    
  3.     public BigDecimal promotion(Order order, int[] promotions){   
  4.         for(int promotion:promotions){   
  5.             switch (promotion){   
  6.                 case 1:   
  7.                     //計算該類型折扣后的價格   
  8.                     break;   
  9.                 case 2:   
  10.                     //計算該類型折扣后的價格   
  11.                     break;   
  12.                 case 3:   
  13.                     //計算該類型折扣后的價格   
  14.                     break;   
  15.                 //....   
  16.             }   
  17.         }   
  18.         return order.getResultPrice();   
  19.     }   

 

單從功能實現上來說,上面的代碼已經完成了基本功能了。

但是上面的代碼也是致命的,雖然看起來很簡單,但是那只不過是因為大多數功能都用注釋代替了,換成實際代碼的話一個方法可能就得上千行。

尤其是當我們需要添加新的促銷活動的話就需要在switch中添加新的類型,這對于開發來說簡直是災難,并且維護這些代碼也是一個麻煩。

優化一:單一職責原則

上面的代碼中,promotion(…)方法直接完成了所有的工作,但是咋我們實際實現中最好讓一個方法的職責單一,只完成某一個功能,所以這里我們將對折扣類型的判斷和計算價格分開:

 

  1. public class OrderPromotion {   
  2.    
  3.     public BigDecimal promotion(Order order, int[] promotions){   
  4.         for(int promotion:promotions){   
  5.             switch (promotion){   
  6.                 case 1:   
  7.                     calculate1(order);   
  8.                     break;   
  9.                 case 2:   
  10.                     calculate2(order);   
  11.                     break;   
  12.                 case 3:   
  13.                     calculate3(order);   
  14.                     break;   
  15.                 //more promotion   
  16.             }   
  17.         }   
  18.         return order.getResultPrice();   
  19.     }   
  20.    
  21.     public void calculate1(Order order){   
  22.         //計算使用折扣一后的價格   
  23.     }   
  24.    
  25.     public void calculate2(Order order){   
  26.         //計算使用折扣二后的價格   
  27.     }   
  28.    
  29.     public void calculate3(Order order){   
  30.         //計算使用折扣三后的價格   
  31.     }   
  32.    
  33.     //more calculate   
  34.    

 

這里我們將折扣類型的判斷和計算價格分開,使得promotion(…)方法的代碼量大大降低,提升了代碼的可讀性。面象對象設計6大原則之一:單一職責原則,這篇也推薦大家看下。

優化二:策略模式

上面優化后的代碼提升了原有代碼的可讀性,但是原來OrderPromotion類代碼大爆炸的問題還是沒有解決。

針對這個問題,我們希望能夠將計算的代碼和當前代碼分離開,首先我們能想到的就是定義一個類,然后將計算的代碼復制到這個類中,需要的時候就調用。這樣到的確是分離開了,但是完全是治標不治本。在添加新的促銷活動是兩個類都要改。

所以我們希望能夠將不同的促銷活動的實現分離開,這樣對每一種活動的實現都是分開的,修改也不會影響其他的,基于此我們完全可以選擇策略模式來實現。

策略模式

策略模式的思想是針對一組算法,將每一種算法都封裝到具有共同接口的獨立的類中,從而是它們可以相互替換。策略模式的最大特點是使得算法可以在不影響客戶端的情況下發生變化,從而改變不同的功能。

 

 

 

 

 

  1. public class OrderPromotion {   
  2.    
  3.     public BigDecimal promotion(Order orderint[] promotions){   
  4.         for(int promotion:promotions){   
  5.             switch (promotion){   
  6.                 case 1:   
  7.                     new PromotionType1Calculate(order);   
  8.                     break;   
  9.                 case 2:   
  10.                     new PromotionType1Calculate(order);   
  11.                     break;   
  12.                 case 3:   
  13.                     new PromotionType1Calculate(order);   
  14.                     break;   
  15.                 //more promotion   
  16.             }   
  17.         }   
  18.         return order.getResultPrice();   
  19.     }   

 

上面的代碼很明顯已經精簡很多了,到了現在如果需要添加一個促銷活動的話只需定義一個促銷類,實現PromotionCalculation接口然后在switch中添加即可。

優化三:工廠模式

上面的代碼雖然已經將促銷活動的實現分離開了,但是OrderPromotion還是一直在變得,每一次添加或者下線活動都需要修改該類。

現在我們希望OrderPromotion是不變的,將PromotionCalculation的實例化剝離開來。創建類很明顯是使用工廠設計模式了。

OrderPromotion

 

  1. public class OrderPromotion {   
  2.    
  3.     public BigDecimal promotion(Order orderint[] promotions){   
  4.         for(int promotion:promotions){   
  5.             PromotionFactory.getPromotionCalculate(promotion).calculate(order);   
  6.         }   
  7.         return order.getResultPrice();   
  8.     }   

 

類的創建工作交給工廠來實現。

 

  1. public class PromotionFactory {   
  2.    
  3.     public static PromotionCalculate getPromotionCalculate(int promotion){   
  4.         switch (promotion){   
  5.             case 1:   
  6.                 return new PromotionType1Calculate(order);   
  7.             break;   
  8.             case 2:   
  9.                 return new PromotionType1Calculate(order);   
  10.             break;   
  11.             case 3:   
  12.                 return new PromotionType1Calculate(order);   
  13.             break;   
  14.             //more promotion   
  15.         }   
  16.         return null;   
  17.     }   

 

使用工廠模式后OrderPromotion類就不需要改了,每一次添加新的促銷活動后只需要在工廠類中添加即可。

優化四:配置+反射

上面的代碼還存在的問題在于每一次需要添加新的促銷活動的時候還是需要修改工廠類中的代碼,這里我們通過配置文件加反射的方式來解決。

定義映射配置文件

mapping.properties

 

  1. 1=design.order.PromotionType1Calculate   
  2. 2=design.order.PromotionType2Calculate   
  3. 3=design.order.PromotionType3Calculate 

 

PromotionFactory

 

  1. public class PromotionFactory {   
  2.    
  3.     private static Map<Integer, String> mapping = new HashMap<Integer, String>();   
  4.    
  5.     static {   
  6.         try {   
  7.             Properties pps = new Properties();   
  8.             pps.load(new FileInputStream("Test.properties"));   
  9.             Iterator<String> iterator = pps.stringPropertyNames().iterator();   
  10.             while(iterator.hasNext()){   
  11.                 String key=iterator.next();   
  12.                 mapping.put(Integer.valueOf(key), pps.getProperty(key));   
  13.             }   
  14.         } catch (IOException e) {   
  15.             e.printStackTrace();   
  16.         }   
  17.     }   
  18.    
  19.     public static PromotionCalculate getPromotionCalculate(int promotion) throws Exception {   
  20.         if(mapping.containsKey(promotion)){   
  21.             String beanName = mapping.get(promotion);   
  22.             return Class.forName(beanName).newInstance();   
  23.         }   
  24.         return null;   
  25.     }   

 

通過上面的代碼就可以實現不改變已有代碼的前提下實現對功能的靈活擴展。當然,這里的代碼只是作為演示用的,實際上可以改進的地方還有不少,像最后反射效率較低,也可以通過其他的方式來實現。

小結

設計模式是我們一定要了解的東西,熟悉設計模式能讓我們設計出易于擴展和維護的代碼結構。但是并不是任何地方都需要上設計模式,應該結合我們的項目實際進行分析是否需要設計模式,使用哪種設計模式。

 

責任編輯:華軒 來源: 博客園
相關推薦

2021-07-02 20:37:19

Python代碼SRP

2022-05-20 08:09:18

設計模式后端代碼

2022-05-30 11:04:09

云計算多云模式

2009-07-15 18:14:46

學習Jython

2021-09-03 09:06:42

代碼時間開發

2014-04-23 13:13:59

OpenShift

2024-12-03 08:00:00

2009-06-02 10:02:50

eclipse jboeclipse jbojboss for e

2022-07-15 09:01:15

React對象編程

2009-06-25 15:54:18

設計模式EJB

2023-01-01 23:42:22

React框架暗黑模式

2020-12-07 13:23:07

LibreOffice開源

2017-04-13 10:46:14

Webpack執行代碼分割

2024-04-01 00:00:00

AnsibleJenkins應用程序

2022-05-31 08:49:02

Flutter應用程序前端

2011-08-22 16:26:25

IOS開發Sqlite數據庫

2022-09-13 08:32:43

Ubuntu

2015-08-03 16:01:49

Ubuntu應用

2021-07-28 08:31:25

設計系統應用

2013-03-13 10:17:50

混合云混合云模式構建混合云
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 日韩毛片免费视频 | av黄色在线播放 | a毛片 | 亚洲精品欧美 | 亚洲精选久久 | 精品国产乱码久久久久久蜜臀 | 91av大全| 久久av网 | 奇米影视首页 | av天天看| 99视频在线免费观看 | 欧美在线国产精品 | 综合久久综合久久 | 97久久精品午夜一区二区 | 欧美成人一区二区三区 | 亚洲一区视频在线 | 国产在线一区二区三区 | 久草网址| 亚洲一区二区三区视频免费观看 | 国产精品成av人在线视午夜片 | 天天干天天玩天天操 | 精品粉嫩超白一线天av | 粉嫩一区二区三区四区公司1 | aa级毛片毛片免费观看久 | 久久久久久久国产 | 亚洲久久久 | 在线亚洲一区二区 | 久久91av| 国产日韩精品在线 | 国产欧美一区二区精品忘忧草 | 国产亚洲精品美女久久久久久久久久 | 欧美中文字幕一区二区三区亚洲 | 欧美极品一区二区 | 亚洲一二三区在线观看 | 欧美精品在线一区二区三区 | 精品亚洲一区二区三区四区五区 | 精品1区 | 亚州春色 | 日日夜夜天天综合 | 中文字幕一区二区三区精彩视频 | 伊人久操 |