设计模式-软件架构设计七大原则及开闭原则详解
前言
在日常工作中,我們使用Java語言進(jìn)行業(yè)務(wù)開發(fā)的時(shí)候,或多或少的都會(huì)涉及到設(shè)計(jì)模式,而運(yùn)用好設(shè)計(jì)模式對(duì)于我而言,又是一個(gè)比較大的難題。為了解決、克服這個(gè)難題,Remi醬特別開了這個(gè)博客來記錄自己學(xué)習(xí)的筆記和自己的理解,也歡迎對(duì)此有興趣的朋友一起來和博主探討,共同學(xué)習(xí)。
一、軟件架構(gòu)設(shè)計(jì)模式的七大原則
1、開閉原則
對(duì)擴(kuò)展開放,對(duì)修改關(guān)閉。在程序需要擴(kuò)展的時(shí)候,不能去修改原有的代碼實(shí)現(xiàn)一個(gè)熱插拔的效果。簡(jiǎn)而言之,就是用抽象構(gòu)建架構(gòu),用實(shí)現(xiàn)擴(kuò)展細(xì)節(jié)。
2、單一職責(zé)原則
不要存在多于一個(gè)導(dǎo)致類變更的原因。簡(jiǎn)單來說,就是 一個(gè)Class/Interface/Method只負(fù)責(zé)一項(xiàng)職責(zé) 。
3、依賴倒置原則
這個(gè)原則是開閉原則的基礎(chǔ),是指設(shè)計(jì)結(jié)構(gòu)代碼時(shí),高層模塊不應(yīng)該依賴于底層模塊,二者應(yīng)該依賴于抽象。抽象不應(yīng)該依賴于細(xì)節(jié),細(xì)節(jié)應(yīng)該依賴于抽象。即: 針對(duì)接口編程,依賴于抽象而不依賴于具體 。
4、接口隔離原則
使用多個(gè)接口,而不使用單一的接口,客戶端不應(yīng)該依賴它不需要的接口。盡量的 細(xì)化接口的職責(zé),降低類的耦合度 。
5、迪米特法則
又被成為 最少知道原則 ,指的是一個(gè)對(duì)象應(yīng)該對(duì)其他對(duì)象保持最少的了解。一個(gè)實(shí)體類應(yīng)當(dāng)盡量少地和其他實(shí)體之間發(fā)生相互作用,使得系統(tǒng)模塊相互獨(dú)立。形象來說就是:只和朋友交流,不和陌生人說話。
6、里氏替換原則
如果說實(shí)現(xiàn)開閉原則的關(guān)鍵步驟就是抽象化,那么基類(父類)和子類的繼承關(guān)系就是抽象化的具體實(shí)現(xiàn),所以里氏替換原則就是對(duì)實(shí)現(xiàn)抽象化的具體步驟的規(guī)范。即:子類可以擴(kuò)展基類(父類)的功能,但不能改變父類原有的功能。
7、合成復(fù)用原則
盡量使用對(duì)象組合/聚合,而不是使用繼承達(dá)到軟件復(fù)用的目的??梢允瓜到y(tǒng)更加的靈活,降低類與類之間的耦合度,一個(gè)類的變化對(duì)于其他類來說影響相對(duì)較少。
繼承我們稱之為白箱復(fù)用,相當(dāng)于把實(shí)現(xiàn)的細(xì)節(jié)暴露給子類,組合/聚合 也成為黑箱復(fù)用,對(duì)類之外的對(duì)象是無法獲取到實(shí)現(xiàn)細(xì)節(jié)的。
二、開閉原則詳解
對(duì)擴(kuò)展開放,對(duì)修改關(guān)閉。在程序需要擴(kuò)展的時(shí)候,不能去修改原有的代碼實(shí)現(xiàn)一個(gè)熱插拔的效果。簡(jiǎn)而言之,就是用抽象構(gòu)建架構(gòu),用實(shí)現(xiàn)擴(kuò)展細(xì)節(jié)。
光看理論是不行的,這樣的話我們只能是有一個(gè)模糊的認(rèn)識(shí),對(duì)具體的細(xì)節(jié)不太能看得清,我們先來舉一個(gè)例子看一看它是怎么使用的:
例:假如我們居住的附近有一個(gè)小超市開業(yè)了,里面有各種的商品。老板想找你幫忙做一個(gè)超市商品的管理系統(tǒng),那么針對(duì)超市眾多商品的情況,我們首先應(yīng)該會(huì)想到創(chuàng)建一個(gè)類來顯示商品的基本信息:價(jià)格、名稱等, 針對(duì)此,我們先來創(chuàng)建一個(gè)接口:
/*** 商品基本信息 接口*/ public interface Goods {/*** 商品的價(jià)格*/void getPrice();/*** 商品的名稱*/void getName(); } 我們發(fā)現(xiàn)超市里有薯片販賣,我們?cè)賮韺懸粋€(gè)薯片的類來實(shí)現(xiàn)這個(gè)接口,同時(shí)標(biāo)明薯片的名稱和價(jià)格:/*** 樂事薯片*/ public class Crisps implements Goods{@Overridepublic void getPrice() {System.out.println("商品的價(jià)格:9.9 RMB");}@Overridepublic void getName() {System.out.println("商品的名稱:樂事薯片");} } 老板說以后還會(huì)有面包出售,那我們?cè)賮韯?chuàng)建一個(gè)類來表明面包的基本信息:/*** 面包*/ public class Bread implements Goods{@Overridepublic void getPrice() {System.out.println("商品的價(jià)格:5.5 RMB");}@Overridepublic void getName() {System.out.println("商品的名稱:面包");} }等把這一切做好后,老板說因?yàn)樾碌陝倓傞_業(yè),沒有什么人氣,就想前期通過薯片打折的方式來吸引人氣(薯片打六折),這個(gè)時(shí)候我們想到的是:
1、修改 Crisps 類中的 getPrice() 方法,但這會(huì)有一定的風(fēng)險(xiǎn),可能會(huì)影響其他地方的調(diào)用結(jié)果。那么這個(gè)方法就可以pass掉。
2、在 Goods 接口中再加一個(gè)方法獲取打折后的價(jià)格,但最后發(fā)現(xiàn) Bread 類也需要去實(shí)現(xiàn)這個(gè)方法,但是面包并沒有打折,這就對(duì)接口其他的實(shí)現(xiàn)類造成了影響,顯然不可取。
3、在 Crisps 類中再加入一個(gè)方法來獲得打折后的薯片價(jià)格,但這樣可能會(huì)改變 Crisps 類的結(jié)構(gòu),可能會(huì)造成不必要的麻煩,而且開閉原則的基礎(chǔ)就是:擴(kuò)展程序的時(shí)候不能去修改原有的代碼。那么這個(gè)方法也被pass。
4、在增加一個(gè)類去繼承 Crisps 類,在子類中增加一個(gè)方法獲取打折后的價(jià)格,這樣通過子類我們可以獲取到商品的名稱,打折前的價(jià)格,打折后的價(jià)格,也不會(huì)改變 Crisps 類原有的結(jié)構(gòu),符合我們的規(guī)范,那我們?cè)賮砭帉懸粋€(gè)類。
/*** 薯片的子類*/ public class CrispsDisCountPrice extends Crisps {/*** 打折后的價(jià)格*/public void getDisCountPrice(){System.out.println("打折后的價(jià)格:"+ 9.9*0.6 +" RMB");} }我們來看一下類的結(jié)構(gòu)圖:
Crisps 類和 Bread 類是接口 Goods 的實(shí)現(xiàn)類,而 CrispsDisCountPrice 類繼承了 Crisps 類。
寫個(gè)測(cè)試類測(cè)試一下:
public class Test {public static void main(String[] args) {Bread bread = new Bread();CrispsDisCountPrice crisps = new CrispsDisCountPrice();bread.getName();bread.getPrice();crisps.getName();crisps.getPrice();crisps.getDisCountPrice();} }結(jié)果:
最后
學(xué)習(xí)設(shè)計(jì)模式不能只理解于理論,要根據(jù)例子理解才能更加的清晰、透徹。接下來的幾篇博客,我會(huì)將設(shè)計(jì)模式剩下的六個(gè)原則都一一說明,并舉一例子。講完七大原則后,會(huì)重點(diǎn)解析我們常說的23種設(shè)計(jì)模式。這是我學(xué)習(xí)記錄的一個(gè)過程,謝謝!
文章來源:https://www.tuicool.com/articles/7BVnqyq
作者:博客園
總結(jié)
以上是生活随笔為你收集整理的设计模式-软件架构设计七大原则及开闭原则详解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Spring系列之集成MongoDB的2
- 下一篇: asp.net ajax控件工具集 Au