java設計模式精講 Debug 方式+記憶體分析 第3章 軟體設計七大原則
軟體設計七大原則
- 3-1 本章導航
- 3-2 開閉原則講解
- 3-3 開閉原則coding
- 3-4 依賴倒置原則講解+coding
- 3-5 單一職責原則講解
- 3-6 單一職責原則coding
- 3-7 介面隔離原則講解+coding
- 3-8 迪米特法則講解+coding
- 3-9 里氏替換原則講解
- 3-10 里氏替換原則coding
- 3-11 合成複用原則講解+coding
3-1 本章導航
3-2 開閉原則講解
實現開閉原則的核心思想就是面向抽象程式設計而不是面向具體的實現程式設計。
3-3 開閉原則coding
- 首先定義一個課程的介面:
public interface ICourse {
Integer getId();
String getName();
Double getPrice();
}
- 定義一個Java課程的類並且實現課程介面:
public class JavaCourse implements ICourse {
private Integer id;
private String name;
private Double price;
public JavaCourse(Integer id, String name, Double price) {
this.id = id;
this.name = name;
this.price = price;
}
@Override
public Integer getId() {
return this.id;
}
@Override
public String getName() {
return this.name;
}
@Override
public Double getPrice() {
return this.price;
}
}
- 定義一個Test測試類:
public class Test {
public static void main(String[]args){
ICourse javaCourse = new JavaCourse(96, "Java 從零開始到企業級開發", 348d);
System.out.println("課程Id:" + javaCourse.getId() + "課程名稱:" + javaCourse.getName() + "課程價格:" + javaCourse.getPrice());
}
}
輸出結果如下:
課程Id:96課程名稱:Java 從零開始到企業級開發課程價格:348.0
現在的類結構圖如圖所示:
假如現在雙十一的時候,要進行課程的打折活動:我們應該如何去做呢 ?
我們可以這樣來做:
新增一個計算打折價格的方法:
public interface ICourse {
Integer getId();
String getName();
Double getPrice();
Double getDiscountPrice();
}
同樣實現類也要實現這個方法:
public class JavaCourse implements ICourse {
private Integer id;
private String name;
private Double price;
public JavaCourse(Integer id, String name, Double price) {
this.id = id;
this.name = name;
this.price = price;
}
@Override
public Integer getId() {
return this.id;
}
@Override
public String getName() {
return this.name;
}
@Override
public Double getPrice() {
return this.price;
}
@Override
public Double getDiscountPrice() {
return this.price*0.8;
}
}
在Test類裡面,我們就是可以這樣來進行獲取:
public class Test {
public static void main(String[]args){
ICourse javaCourse = new JavaCourse(96, "Java 從零開始到企業級開發", 348d);
System.out.println("課程Id:" + javaCourse.getId() + "課程名稱:" + javaCourse.getName() + "課程價格:" + javaCourse.getPrice()+"雙十一打折價格:"+javaCourse.getDiscountPrice());
}
}
輸出結果如下:
課程Id:96課程名稱:Java 從零開始到企業級開發課程價格:348.0雙十一打折價格:278.40000000000003
但是,這種方法不好,假如課程很多,那麼所有的課程的實現類都要重寫一下方法,介面應該是穩定的,不應該是經常修改的。
我們再換一種方法:
我們寫一個Java課程打折類並且繼承於Java課程類,之前的課程類裡面的價格就不打折了:
public class JavaDiscountCourse extends JavaCourse {
public JavaDiscountCourse(Integer id, String name, Double price) {
super(id, name, price);
}
@Override
public Double getPrice() {
return super.getPrice()*0.8;
}
}
然後,我們在測試的時候,就是可以直接指向Java課程打折類的這個物件就可以了:
public class Test {
public static void main(String[]args){
ICourse javaCourse = new JavaDiscountCourse(96, "Java 從零開始到企業級開發", 348d);
System.out.println("課程Id:" + javaCourse.getId() + "課程名稱:" + javaCourse.getName() + "課程價格:" + javaCourse.getPrice());
}
}
這個時候的結果就是:這裡有丟失精度的問題,可以使用String構造器的BigDecimal來解決
課程Id:96課程名稱:Java 從零開始到企業級開發課程價格:222.72000000000003
如果我們還想要原價,我們可以這樣來做:
public class JavaDiscountCourse extends JavaCourse {
public JavaDiscountCourse(Integer id, String name, Double price) {
super(id, name, price);
}
/** 獲取原價的方法 */
public Double getOriginPrice() {
return super.getPrice();
}
@Override
public Double getPrice() {
return super.getPrice()*0.8;
}
}
這個時候,我們就是可以這樣來呼叫:
public class Test {
public static void main(String[]args){
ICourse iCourse = new JavaDiscountCourse(96, "Java 從零開始到企業級開發", 348d);
/** 如果呼叫實現類裡面的方法,我們就必須要進行強轉一下 */
JavaDiscountCourse javaCourse = (JavaDiscountCourse)iCourse;
System.out.println("課程Id:" + javaCourse.getId() + "課程名稱:" + javaCourse.getName() + "課程價格:"+javaCourse.getOriginPrice()+"課程折後價格:" + javaCourse.getPrice());
}
}
執行結果如下:
課程Id:96課程名稱:Java 從零開始到企業級開發課程價格:348.0課程折後價格:278.40000000000003
現在的類圖如圖所示:
我們通過了繼承了基類,然後對其進行擴充套件,對擴充套件是開發的,而對修改介面和基類是關閉的;
越是基層的模組的修改影響的範圍是越大的。
3-4 依賴倒置原則講解+coding
依賴倒置原則的核心就是:面向介面程式設計
有一個類:裡面有兩個方法,一個學習java課程的方法,一個是學習FE課程的方法:
public class Tom {
public void studyJavaCourse() {
System.out.println("Tom在學習Java課程");
}
public void studyFECourse() {
System.out.println("Tom在學習FE課程");
}
}
這個時候,我們寫上一個測試類:
public class Test {
public static void main(String[]args){
Tom tom = new Tom();
tom.studyJavaCourse();
tom.studyFECourse();
}
}
如果這個時候,我還想要新增一個學習Python課程的方法,這個時候,我可以在基類裡面進行新增方法:
public class Tom {
public void studyJavaCourse() {
System.out.println("Tom在學習Java課程");
}
public void studyFECourse() {
System.out.println("Tom在學習FE課程");
}
public void studyPythonCourse() {
System.out.println("Tom在學習Python課程");
}
}
以上我們的做法就是在面向實現來進行程式設計,面向實現類來進行程式設計的話, 擴充套件性比較的差,這個就是依賴於底層的實現的
現在我們來引入抽象來解決這個問題:
- 首先寫上一個課程介面:
public interface ICourse {
void studyCourse();
}
- 有兩個實現類:一個是學習Java的實現類,一個是學習前端的實現類,分別是:
public class JavaCourse implements ICourse {
@Override
public void studyCourse() {
System.out.println("Tom在學習Java課程");
}
}
public class FECourse implements ICourse {
@Override
public void studyCourse() {
System.out.println("Tom在學習FE課程");
}
}
原來的Tom類,我們就要進行重構了,寫了一個學習課程的方法,傳入了學習課程的介面,由具體的實現類來進行實現:
具體學了哪些課程,是由具體的實現類來決定的:
public class Tom {
public void studyCourse(ICourse iCourse) {
iCourse.studyCourse();
}
}
我們對其進行測試:
public class Test {
public static void main(String[]args){
Tom tom = new Tom();
tom.studyCourse(new JavaCourse());
tom.studyCourse(new FECourse());
}
}
執行結果為:
Tom在學習Java課程
Tom在學習FE課程
這個時候,如果還要學習Python的課程的話,那我們就可以再寫上一個實現類來對介面進行實現即可:
public class PythonCourse implements ICourse {
@Override
public void studyCourse() {
System.out.println("Tom在學習Python課程");
}
}
我們就可以來呼叫了:
public class Test {
public static void main(String[]args){
Tom tom = new Tom();
tom.studyCourse(new JavaCourse());
tom.studyCourse(new FECourse());
tom.studyCourse(new PythonCourse());
}
}
輸出結果:
Tom在學習Java課程
Tom在學習FE課程
Tom在學習Python課程
以上是通過介面方法的方式來注入具體的實現;
當然,我們也可以通過構造器的方式來注入具體的實現:
在Tom這個類裡面寫一個構造器,把介面作為Tom類裡面的一個成員屬性,然後通過構造器來對其進行賦值:
public class Tom {
private ICourse iCourse;
public Tom(ICourse iCourse) {
this.iCourse = iCourse;
}
/** 這裡的方法,就只需要呼叫類成員變數ICourse裡面的studyCourse()方法就可以了 */
public void studyCourse() {
iCourse.studyCourse();
}
}
測試:
public class Test {
public static void main(String[]args){
Tom tom = new Tom(new JavaCourse());
tom.studyCourse();
}
}
測試結果:
Tom在學習Java課程
以上的用構造器來進行傳遞介面的實現,也不是很好,每次學一個新的課程的時候,還有重新new一個類;
這個時候,我們可以利用set方法來進行注入:
public class Tom {
private ICourse iCourse;
public void setiCourse(ICourse iCourse) {
this.iCourse = iCourse;
}
public void studyCourse() {
iCourse.studyCourse();
}
}
這個時候,我們就是可以這樣來用了:
public class Test {
public static void main(String[]args){
Tom tom = new Tom();
tom.setiCourse(new JavaCourse());
tom.studyCourse();
tom.setiCourse(new FECourse());
tom.studyCourse();
}
}
執行結果:
Tom在學習Java課程
Tom在學習FE課程
現在的類圖:
3-5 單一職責原則講解
3-6 單一職責原則coding
我們寫一個Bird類:
public class Bird {
public void mainMoveMode(String birdName) {
System.out.println(birdName+"用翅膀飛");
}
}
測試類:
public class Test {
public static void main(String[]args){
Bird bird = new Bird();
bird.mainMoveMode("大雁");
bird.mainMoveMode("鴕鳥");
}
}
輸出結果:
大雁用翅膀飛
鴕鳥用翅膀飛
那麼現在就是有問題的 ,鴕鳥不是用翅膀飛的。
這個時候,我們在原來Bird類裡面進行擴充套件:這個時候,是不遵循單一職責原則的
public class Bird {
public void mainMoveMode(String birdName) {
if ("鴕鳥".equals(birdName)) {
System.out.println(birdName + "用腳走");
} else {
System.out.println(birdName+"用翅膀飛");
}
}
}
這個時候的執行結果就是:
大雁用翅膀飛
鴕鳥用腳走
這個時候,我們按照職責的不同來進行拆分:
會飛的鳥:
public class FlyBird {
public void mainMoveMode(String birdName) {
System.out.println(birdName+"用翅膀飛");
}
}
用腳走路的鳥:
public class WalkBird {
public void mainMoveMode(String birdName) {
System.out.println(birdName+"用腳走");
}
}
測試:
public class Test {
public static void main(String[]args){
FlyBird flyBird = new FlyBird();
flyBird.mainMoveMode("大雁");
WalkBird walkBird = new WalkBird();
walkBird.mainMoveMode("鴕鳥");
}
}
執行結果:
大雁用翅膀飛
鴕鳥用腳走
這個就是現在的類圖:
這個接口裡面含有兩個大塊的功能:一個是獲取課程的相關的資訊,一個是對課程進行管理:
public interface ICourse {
/** 或者課程的相關的資訊 */
String getCourseName();
byte[] getCourseVideo();
/** 課程管理上的 */
void studyCourse();
void refundCourse();
}
這個時候,我們就是可以對上面的介面進行一個拆分:
public interface ICourseContent {
/** 或者課程的相關的資訊 */
String getCourseName();
byte[] getCourseVideo();
}
public interface ICourseManager {
/** 課程管理上的 */
void studyCourse();
void refundCourse();
}
我們寫一個實現類,來實現上面的兩個介面:|
public class CourseImpl implements ICourseManager,ICourseContent {
@Override
public String getCourseName() {
return null;
}
@Override
public byte[] getCourseVideo() {
return new byte[0];
}
@Override
public void studyCourse() {
}
@Override
public void refundCourse()
相關推薦
java設計模式精講 Debug 方式+記憶體分析 第3章 軟體設計七大原則
軟體設計七大原則
3-1 本章導航
3-2 開閉原則講解
3-3 開閉原則coding
3-4 依賴倒置原則講解+coding
3-5 單一職責原則講解
3-6 單一職責原則coding
3-7 介面隔離原則講解+coding
java設計模式精講 Debug 方式+記憶體分析-第2章 UML急速入門
java設計模式精講 Debug 方式+記憶體分析-第2章
2-1 本章導航
UML的定義
UML的特點
UML2.2的分類
UML類圖
記憶技巧
UML時序圖
2-2 UML類圖講解
2-3
java設計模式精講 Debug 方式+記憶體分析 第5章 工廠方法模式
工廠方法模式
5-1 工廠方法講解
5-2 工廠方法coding
5-3 工廠方法原始碼解析(jdk+logback)
5-1 工廠方法講解
5-2 工廠方法coding
業務場景和之前的簡
java設計模式精講 Debug 方式+記憶體分析 第4章 簡單工廠模式
簡單工廠模式
4-1 簡單工廠講解
4-2 簡單工廠coding
4-3 簡單工廠JDK原始碼解析
4-1 簡單工廠講解
4-2 簡單工廠coding
有一個視訊的基類(是一個抽
java設計模式精講 Debug 方式+記憶體分析 第7章 建造者模式
建造者模式
7-1 建造者模式講解
7-2 建造者模式coding
7-3 建造者模式原始碼解析(jdk+guava+spring+mybatis)
7-1 建造者模式講解
7-2 建造者
java設計模式精講 Debug 方式+記憶體分析 第6章 抽象工廠模式
抽象工廠模式
6-1 抽象工廠講解
6-2 抽象工廠coding
6-3 抽象工廠原始碼解析
6-1 抽象工廠講解
工廠方法模式針對的就是產品等級結構 而抽象方法模
java設計模式精講 Debug 方式+記憶體分析 第14章 組合模式講解
組合模式
14-1 組合模式講解
14-2 組合模式coding
14-3 組合模式原始碼解析(jdk+mybatis)
14-1 組合模式講解
14-2 組合模式
java設計模式精講 Debug 方式+記憶體分析 第13章 享元模式
享元模式
13-1 享元模式講解
13-2 享元設計模式coding
13-3 享元模式原始碼解析(jdk+tomcat)
13-1 享元模式講解
13-2 享元設
java設計模式精講 Debug 方式+記憶體分析 第12章 介面卡模式
介面卡模式
12-1 介面卡模式講解
12-2 介面卡模式coding
12-3 介面卡模式原始碼解析(jdk+spring+springjpa+springmvc)
12-1 介面卡模式講解
java設計模式精講 Debug 方式+記憶體分析 第11章 裝飾者模式
裝飾者模式
11-1 裝飾者模式講解
11-2 裝飾者模式coding
11-3 裝飾者模式原始碼解析(spring-session mybatis jdk servlet)
11-1 裝飾者模式講解
java設計模式精講 Debug 方式+記憶體分析 第10章 外觀模式
外觀模式
10-1 外觀模式講解
11-2 裝飾者模式coding
11-3 裝飾者模式原始碼解析(spring-session mybatis jdk servlet)
10-1 外觀模式講解
java設計模式精講 Debug 方式+記憶體分析 第9章 原型模式
原型模式
9-1 原型模式講解
9-2 原型模式coding
9-3 原型模式coding-克隆破壞單例
9-4 原型模式原始碼解析
9-1 原型模式講解
9-2 原型模
java設計模式精講 Debug 方式+記憶體分析 第8章 單例模式
單例模式
8-1 單例模式講解
8-2 單例設計模式-懶漢式及多執行緒Debug實戰
8-3 單例設計模式-DoubleCheck雙重檢查實戰及原理解析
8-4 單例設計模式-靜態內部類-基於類初始化的延遲載入解決方案及原理解析
8-5 單例設計
java設計模式精講 Debug 方式+記憶體分析-第2章
2-1 本章導航
UML的定義
UML的特點
UML2.2的分類
結構式圖形
行為式圖形
互動式圖形
UML類圖
記憶技巧
UML時序圖
黑色的實線和實心箭頭表示同步呼叫
黑色的實線和空心箭頭表示非同步
java設計模式精講 Debug 方式記憶體分析
下載地址:獲取資源
第1章 課程導學
本章節主要講解大家能收穫什麼,課程具體包含哪些內容,通過哪些方式來學習設計模式,以及怎麼講,怎麼安排,通過本章的學習,讓大家為整個課程高效的學習打下基礎。
1-1 課程導學 第2章 UML急速入門
本章節主要講解UML基礎、UML類圖、
java設計模式精講 Debug 方式+記憶體分析完整版
第1章 課程導學(提供問答區答疑解惑)本章節主要講解大家能收穫什麼,課程具體包含哪些內容,通過哪些方式來學習設計模式,以及怎麼講,怎麼安排,通過本章的學習,讓大家為整個課程高效的學習打下基礎。1-1 課程導學第2章 UML急速入門本章節主要講解UML基礎、UML類圖、UML類關係、UML時序圖
馬哥java設計模式精講 Debug 方式+記憶體分析
第1章 課程導學(提供問答區答疑解惑)本章節主要講解大家能收穫什麼,課程具體包含哪些內容,通過哪些方式來學習設計模式,以及怎麼講,怎麼安排,通過本章的學習,讓大家為整個課程高效的學習打下基礎。1-1 課程導學第2章 UML急速入門本章節主要講解UML基礎、UML類圖、UM
java設計模式精講 Debug 方式+記憶體分析(雲盤下載)
第1章 課程導學(提供問答區答疑解惑)本章節主要講解大家能收穫什麼,課程具體包含哪些內容,通過哪些方式來學習設計模式,以及怎麼講,怎麼安排,通過本章的學習,讓大家為整個課程高效的學習打下基礎。1-1 課程導學第2章 UML急速入門本章節主要講解UML基礎、UML類圖、UM
某課最新java設計模式精講 Debug 方式+記憶體分析
第1章 課程導學(提供問答區答疑解惑)本章節主要講解大家能收穫什麼,課程具體包含哪些內容,通過哪些方式來學習設計模式,以及怎麼講,怎麼安排,通過本章的學習,讓大家為整個課程高效的學習打下基礎。1-1 課程導學第2章 UML急速入門本章節主要講解UML基礎、UML類圖、UML類
java設計模式精講 Debug 方式+記憶體分析目前最全
第1章 課程導學(提供問答區答疑解惑)本章節主要講解大家能收穫什麼,課程具體包含哪些內容,通過哪些方式來學習設計模式,以及怎麼講,怎麼安排,通過本章的學習,讓大家為整個課程高效的學習打下基礎。1-1 課程導學第2章 UML急速入門本章節主要講解UML基礎、UML類圖、UM