前言
在日常工作中,我們使用Java語言進行業務開發的時候,或多或少的都會涉及到設計模式,而運用好設計模式對於我而言,又是一個比較大的難題。為了解決、克服這個難題,筆主特別開了這個博客來記錄自己學習的筆記和自己的理解,也歡迎對此有興趣的朋友一起來和筆主探討,共同學習。
一、軟件架構設計模式的七大原則
1、開閉原則
對擴展開放,對修改關閉。在程序需要擴展的時候,不能去修改原有的代碼實現一個熱插拔的效果。簡而言之,就是用抽象構建架構,用實現擴展細節。
2、單一職責原則
不要存在多於一個導致類變更的原因。簡單來說,就是一個Class/Interface/Method只負責一項職責。
3、依賴倒置原則
這個原則是開閉原則的基礎,是指設計結構代碼時,高層模塊不應該依賴於底層模塊,二者應該依賴於抽象。抽象不應該依賴於細節,細節應該依賴於抽象。即:針對接口編程,依賴於抽象而不依賴於具體。
4、接口隔離原則
使用多個接口,而不使用單一的接口,客戶端不應該依賴它不需要的接口。盡量的細化接口的職責,降低類的耦合度。
5、迪米特法則
又被成為最少知道原則,指的是一個對象應該對其他對象保持最少的了解。一個實體類應當盡量少地和其他實體之間發生相互作用,使得系統模塊相互獨立。形象來說就是:只和朋友交流,不和陌生人說話。
6、里氏替換原則
如果說實現開閉原則的關鍵步驟就是抽象化,那么基類(父類)和子類的繼承關系就是抽象化的具體實現,所以里氏替換原則就是對實現抽象化的具體步驟的規范。即:子類可以擴展基類(父類)的功能,但不能改變父類原有的功能。
7、合成復用原則
盡量使用對象組合/聚合,而不是使用繼承達到軟件復用的目的。可以使系統更加的靈活,降低類與類之間的耦合度,一個類的變化對於其他類來說影響相對較少。
繼承我們稱之為白箱復用,相當於把實現的細節暴露給子類,組合/聚合 也成為黑箱復用,對類之外的對象是無法獲取到實現細節的。
二、開閉原則詳解
對擴展開放,對修改關閉。在程序需要擴展的時候,不能去修改原有的代碼實現一個熱插拔的效果。簡而言之,就是用抽象構建架構,用實現擴展細節。
光看理論是不行的,這樣的話我們只能是有一個模糊的認識,對具體的細節不太能看得清,我們先來舉一個例子看一看它是怎么使用的:
例:假如我們居住的附近有一個小超市開業了,里面有各種的商品。老板想找你幫忙做一個超市商品的管理系統,那么針對超市眾多商品的情況,我們首先應該會想到創建一個類來顯示商品的基本信息:價格、名稱等, 針對此,我們先來創建一個接口:
/**
* 商品基本信息 接口
*/
public interface Goods {
/**
* 商品的價格
*/
void getPrice();
/**
* 商品的名稱
*/
void getName();
}
我們發現超市里有薯片販賣,我們再來寫一個薯片的類來實現這個接口,同時標明薯片的名稱和價格:
/**
* 樂事薯片
*/
public class Crisps implements Goods{
@Override
public void getPrice() {
System.out.println("商品的價格:9.9 RMB");
}
@Override
public void getName() {
System.out.println("商品的名稱:樂事薯片");
}
}
老板說以后還會有面包出售,那我們再來創建一個類來表明面包的基本信息:
/**
* 面包
*/
public class Bread implements Goods{
@Override
public void getPrice() {
System.out.println("商品的價格:5.5 RMB");
}
@Override
public void getName() {
System.out.println("商品的名稱:面包");
}
}
等把這一切做好后,老板說因為新店剛剛開業,沒有什么人氣,就想前期通過薯片打折的方式來吸引人氣(薯片打六折),這個時候我們想到的是:
1、修改
Crisps
類中的getPrice()
方法,但這會有一定的風險,可能會影響其他地方的調用結果。那么這個方法就可以pass掉。2、在
Goods
接口中再加一個方法獲取打折后的價格,但最后發現Bread
類也需要去實現這個方法,但是面包並沒有打折,這就對接口其他的實現類造成了影響,顯然不可取。3、在
Crisps
類中再加入一個方法來獲得打折后的薯片價格,但這樣可能會改變Crisps
類的結構,可能會造成不必要的麻煩,而且開閉原則的基礎就是:擴展程序的時候不能去修改原有的代碼。那么這個方法也被pass。4、在增加一個類去繼承
Crisps
類,在子類中增加一個方法獲取打折后的價格,這樣通過子類我們可以獲取到商品的名稱,打折前的價格,打折后的價格,也不會改變Crisps
類原有的結構,符合我們的規范,那我們再來編寫一個類。
/**
* 薯片的子類
*/
public class CrispsDisCountPrice extends Crisps {
/**
* 打折后的價格
*/
public void getDisCountPrice(){
System.out.println("打折后的價格:"+ 9.9*0.6 +" RMB");
}
}
我們來看一下類的結構圖:
Crisps
類和Bread
類是接口Goods
的實現類,而CrispsDisCountPrice
類繼承了Crisps
類。
寫個測試類測試一下:
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();
}
}
結果:
最后
學習設計模式不能只理解於理論,要根據例子理解才能更加的清晰、透徹。接下來的幾篇博客,我會將設計模式剩下的六個原則都一一說明,並舉一例子。講完七大原則后,會重點解析我們常說的23種設計模式。這是我學習記錄的一個過程,謝謝!