I walk very slowly, but I never walk backwards
設計模式原則 - 開閉原則
? 寂然
大家好,我是寂然~怔鳖,本節(jié)課呢杠河,我來給大家介紹設計模式原則之開閉原則,話不多說川背,我們直接進入正題,老規(guī)矩,首先帶大家了解一下開閉原則的官方定義,并作一個解釋次和,然后我們通過案例代碼來具體分析
官方定義
開閉原則( Open Close Principle ),又稱為OCP原則那伐,他的官方定義如下:
Software entities like classes,modules and functions should be open for extension but closed for modifications.
一個軟件實體如類踏施,模塊和函數(shù)應該對擴展開放,對修改關(guān)閉
基本介紹
對擴展開放指的是提供方罕邀,對修改關(guān)閉指的是調(diào)用方
一個軟件產(chǎn)品只要在生命周期內(nèi)畅形,都會發(fā)生變化,即然變化是一個事實诉探,我們就應該在設計時盡量適應這些變化日熬,以提高項目的穩(wěn)定性和靈活性,真正實現(xiàn)“擁抱變化”肾胯,開閉原則告訴我們應盡量通過擴展軟件實體的行為來實現(xiàn)變化竖席,而不是通過修改現(xiàn)有代碼來完成變化,它是針對軟件的未來事件而制定的對現(xiàn)行開發(fā)設計進行約束的一個原則
案例演示 - 繪圖工具
OK阳液,大家簡單了解過開閉原則后怕敬,我們來看如下一段代碼,幫助大家更深入的理解
有一個繪圖工具類帘皿,接收 Shape 對象东跪,然后根據(jù)不同的 type,來繪制不同的圖形鹰溜,具體代碼如下圖所示
//這是一個用于繪圖的類 [使用方]
class GraphicEditor {
//接收 Shape 對象虽填,然后根據(jù)不同的 type,來繪制不同的圖形
public void drawShape(Shape s) {
if (s.m_type == 1) {
drawRectangle(s);
} else if (s.m_type == 2) {
drawCircle(s);
}
}
//繪制矩形
public void drawRectangle(Shape r) {
System.out.println(" 正在繪制矩形中---繪制成功 ");
}
//繪制圓形
public void drawCircle(Shape r) {
System.out.println(" 正在繪制圓形中---繪制成功");
}
}
//Shape 類曹动,基類
class Shape {
int m_type;
}
class Rectangle extends Shape {
Rectangle() {
super.m_type = 1;
}
}
class Circle extends Shape {
Circle() {
super.m_type = 2;
}
}
上面這段代碼首先是可以完成需求的斋日,OK,那現(xiàn)在我們新增繪制三角形的功能墓陈,大家想一下實現(xiàn)思路
首先我們要新增 Triangle 類恶守,然后新增繪制三角形的方法第献, drawShap()方法里添加判斷 并調(diào)用就Ok,新增代碼示例如下圖所示
//新增繪制三角形的子類
class Triangle extends Shape {
Triangle() {
super.m_type = 3;
}
}
//類 GraphicEditor 中·添加判斷,type=3,繪制三角形
if (s.m_type == 1) {
drawRectangle(s);
} else if (s.m_type == 2) {
drawCircle(s);
} else if (s.m_type == 3) {
drawTriangle(s);
}
// 類 GraphicEditor 中新增繪制三角形的方法
public void drawTriangle(Shape r) {
System.out.println(" 正在繪制三角形中---繪制成功 ");
}
案例分析
Ok兔港,上面的代碼是比較好理解的庸毫,但是大家想一下,針對上面的業(yè)務邏輯來說衫樊,類 GraphicEditor 扮演的其實是調(diào)用方的角色飒赃,但是出現(xiàn)了新增的需求后,我們對于 類 GraphicEditor 進行了一系列改動科侈,這顯然違背了ocp原則
因為我們上面提到载佳,ocp原則對調(diào)用方的修改是關(guān)閉的,那大家想一下臀栈,新增繪制三角形的功能蔫慧,我們還可以怎么樣實現(xiàn)呢?下面我們在滿足ocp原則的情況下挂脑,對上面的代碼進行重構(gòu)
解決方案
這時有的小伙伴說了藕漱,可以把創(chuàng)建 Shape 類做成抽象類,并提供一個抽象的 draw 方法崭闲,讓子類去實現(xiàn)即可肋联,這樣我們有新的圖形種類時,只需要讓新的圖形類繼承 Shape刁俭,并實現(xiàn) draw 方法即可橄仍,使用方的代碼就不需要修 改了,這樣既滿足了業(yè)務邏輯牍戚,又符合開閉原則侮繁,具體代碼示例如下
//這是一個用于繪圖的類 [使用方]
class GraphicEditor {
//接收 Shape 對象,然后根據(jù)不同的 type如孝,來繪制不同的圖形
public void drawShape(Shape s) {
s.draw();
}
}
//Shape變?yōu)槌橄箢愊芰ǎ⑻峁┏橄骴raw方法
abstract class Shape {
int m_type;
public abstract void draw();//抽象方法
}
class Rectangle extends Shape {
Rectangle() {
super.m_type = 1;
}
@Override
public void draw() {
System.out.println(" 正在繪制矩形中---繪制成功 ");
}
}
class Circle extends Shape {
Circle() {
super.m_type = 2;
}
@Override
public void draw() {
System.out.println(" 正在繪制圓形中---繪制成功 ");
}
}
OK,那這樣的話第晰,同樣還是上面的需求锁孟,我們新增繪制三角形的功能,那我們只需要新建一個 類Shape 的子類茁瘦,實現(xiàn)draw() 方法即可品抽,具體代碼示例如下
class Triangle extends Shape {
Triangle() {
super.m_type = 3;
}
@Override
public void draw() {
System.out.println(" 正在繪制三角形中---繪制成功 ");
}
}
案例總結(jié)
通過上面的重構(gòu),我們可以看到甜熔,當我們新增繪制三角形的功能圆恤,不需要修改調(diào)用方,即本案例中扮演調(diào)用方角色的類 GraphicEditor 不需要修改腔稀,而是擴展了提供方的類盆昙,來完成需求羽历,就遵守了開閉原則,換句話說淡喜,開閉原則要求我們這樣做窄陡,即 針對提供方,對擴展開放拆火,針對調(diào)用方,對修改關(guān)閉
注意事項
- 開閉原則是編程中最基礎(chǔ)涂圆,最重要的設計原則们镜,只要是面向?qū)ο缶幊坛固常陂_發(fā)時都會強調(diào)開閉原則
開閉原則是最基礎(chǔ)的設計原則兑燥,其它的五個設計原則都是開閉原則的具體形態(tài),也就是說其它的五個設計原則是指導設計的工具和方法叫乌,而開閉原則才是其精神領(lǐng)袖踩衩。依照java語言的稱謂嚼鹉,開閉原則是抽象類,而其它的五個原則是具體的實現(xiàn)類
開閉原則可以提高復用性和維護性
下節(jié)預告
OK驱富,下一節(jié)锚赤,我們正式進入設計模式原則之迪 米特法則的學習,我會為大家用多個案例分析褐鸥,來解讀設計模式原則之迪米特法則线脚,以及它的注意事項和細節(jié),最后叫榕,希望大家在學習的過程中浑侥,能夠感覺到設計模式的有趣之處,高效而愉快的學習晰绎,那我們下期見~