解析Java編程中設(shè)計(jì)模式的開閉原則的運(yùn)用
開閉原則(Open Closed Principle)是Java世界里最基礎(chǔ)的設(shè)計(jì)原則,它指導(dǎo)我們?nèi)绾谓⒁粋€(gè)穩(wěn)定的、靈活的系統(tǒng)。
定義:
一個(gè)軟件實(shí)體如類、模塊和函數(shù)應(yīng)該對(duì)擴(kuò)展開放,對(duì)修改關(guān)閉。
Softeware entities like classes,modules and functions should be open for extension but closed for modifications.
開閉原則的含義是說一個(gè)軟件實(shí)體應(yīng)該通過擴(kuò)展來實(shí)現(xiàn)變化,而不是通過修改已有代碼來實(shí)現(xiàn)變化。
軟件實(shí)體包括以下幾個(gè)部分:
- 項(xiàng)目或軟件產(chǎn)品中按照一定的邏輯規(guī)則劃分的模塊
- 抽象和類
- 方法
開閉原則是為軟件實(shí)體的未來事物而制定的對(duì)現(xiàn)行開發(fā)設(shè)計(jì)進(jìn)行約束的一個(gè)原則。
注意:開閉原則對(duì)擴(kuò)展開放,對(duì)修改關(guān)閉,并不意味著不做任何修改,低層模塊的變更,必然要有高層模塊進(jìn)行耦合,否則就是一個(gè)孤立無意義的代碼片段了。
變化的類型:
- 邏輯變化
- 子模塊變化
- 可見試圖變化
一個(gè)項(xiàng)目的基本路徑應(yīng)該是這樣的:項(xiàng)目開發(fā)、重構(gòu)、測(cè)試、投產(chǎn)、運(yùn)維,其中的重構(gòu)可以對(duì)原有的設(shè)計(jì)和代碼進(jìn)行修改,運(yùn)維盡量減少對(duì)原有代碼修改,保持歷史代碼的純潔性,提高系統(tǒng)的穩(wěn)定性。
開閉原則的重要性:
1.開閉原則對(duì)測(cè)試的影響
開閉原則可是保持原有的測(cè)試代碼仍然能夠正常運(yùn)行,我們只需要對(duì)擴(kuò)展的代碼進(jìn)行測(cè)試就可以了。
2.開閉原則可以提高復(fù)用性
在面向?qū)ο蟮脑O(shè)計(jì)中,所有的邏輯都是從原子邏輯組合而來的,而不是在一個(gè)類中獨(dú)立實(shí)現(xiàn)一個(gè)業(yè)務(wù)邏輯。只有這樣代碼才可以復(fù)用,粒度越小,被復(fù)用的可能性就越大。
3.開閉原則可以提高可維護(hù)性
面向?qū)ο箝_發(fā)的要求。
如何使用開閉原則:
1.抽象約束
第一,通過接口或者抽象類約束擴(kuò)展,對(duì)擴(kuò)展進(jìn)行邊界限定,不允許出現(xiàn)在接口或抽象類中不存在的public方法;
第二,參數(shù)類型、引用對(duì)象盡量使用接口或者抽象類,而不是實(shí)現(xiàn)類;
第三,抽象層盡量保持穩(wěn)定,一旦確定即不允許修改。
2.元數(shù)據(jù)(metadata)控制模塊行為
元數(shù)據(jù)就是用來描述環(huán)境和數(shù)據(jù)的數(shù)據(jù),通俗地說就是配置參數(shù),參數(shù)可以從文件中獲得,也可以從數(shù)據(jù)庫(kù)中獲得。
Spring容器就是一個(gè)典型的元數(shù)據(jù)控制模塊行為的例子,其中達(dá)到極致的就是控制反轉(zhuǎn)(Inversion of Control)
3.制定項(xiàng)目章程
在一個(gè)團(tuán)隊(duì)中,建立項(xiàng)目章程是非常重要的,因?yàn)檎鲁讨兄付怂腥藛T都必須遵守的約定,對(duì)項(xiàng)目來說,約定優(yōu)于配置。
4.封裝變化
對(duì)變化的封裝包含兩層含義:
第一,將相同的變化封裝到一個(gè)接口或者抽象類中;
第二,將不同的變化封裝到不同的接口或抽象類中,不應(yīng)該有兩個(gè)不同的變化出現(xiàn)在同一個(gè)接口或抽象類中。
例子
下面來個(gè)例子,先是不好的例子:
class GraphicEditor {
public void drawShape(Shape s) {
if (s.m_type==1)
drawRectangle(s);
else if (s.m_type==2)
drawCircle(s);
}
public void drawCircle(Circle r) {....}
public void drawRectangle(Rectangle r) {....}
}
class Shape {
int m_type;
}
class Rectangle extends Shape {
Rectangle() {
super.m_type=1;
}
}
class Circle extends Shape {
Circle() {
super.m_type=2;
}
}
當(dāng)我們要擴(kuò)展一個(gè)形狀時(shí),需要先了解GraphicEditor類,然后在drawShape中添加新的類型,然后再添加函數(shù)。下面是改進(jìn)后的代碼:
class GraphicEditor {
public void drawShape(Shape s) {
s.draw();
}
}
class Shape {
abstract void draw();
}
class Rectangle extends Shape {
public void draw() {
// draw the rectangle
}
}
不需要了解繪制邏輯,把具體實(shí)現(xiàn)放到了子類。
總結(jié):
1. 遵守開閉原則可以提高軟件擴(kuò)展性和維護(hù)性。
2. 大部分的設(shè)計(jì)模式和設(shè)計(jì)原則都是在實(shí)現(xiàn)開閉原則。
相關(guān)文章
SpringCloud使用Feign實(shí)現(xiàn)遠(yuǎn)程調(diào)用的使用示例
Feign是一個(gè)基于注解的HTTP客戶端庫(kù),它允許您將HTTP請(qǐng)求轉(zhuǎn)換為聲明式的Java接口,本文主要介紹了SpringCloud使用Feign實(shí)現(xiàn)遠(yuǎn)程調(diào)用的使用示例,感興趣的可以了解一下2023-09-09
java基本教程之常用的實(shí)現(xiàn)多線程的兩種方式 java多線程教程
下面開始學(xué)習(xí)“常用的實(shí)現(xiàn)多線程的2種方式”:Thread 和 Runnable。之所以說是常用的,是因?yàn)橥ㄟ^還可以通過java.util.concurrent包中的線程池來實(shí)現(xiàn)多線程2014-01-01
Java遍歷字符串和統(tǒng)計(jì)字符個(gè)數(shù)的操作方法
這篇文章主要介紹了Java遍歷字符串和統(tǒng)計(jì)字符個(gè)數(shù)的操作方法,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧2024-12-12
Java方法的參數(shù)傳遞機(jī)制實(shí)例詳解
這篇文章主要介紹了Java方法的參數(shù)傳遞機(jī)制,結(jié)合實(shí)例形式詳細(xì)分析了java方法參數(shù)傳遞機(jī)制原理、實(shí)現(xiàn)方法及操作注意事項(xiàng),需要的朋友可以參考下2019-09-09
MyBatis創(chuàng)建存儲(chǔ)過程的實(shí)例代碼_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
本節(jié)需要用到的有2部分,第一部分是如何在Derby中創(chuàng)建存儲(chǔ)過程,第二部分是如何在Mybatis中調(diào)用存儲(chǔ)過程,具體實(shí)例代碼大家參考下本文吧2017-09-09

