由一論壇文章 想到的ocp原則

2021-09-01 19:14:41 字數 2751 閱讀 4657

今天閒來無事去社群上逛了一下。發現乙個好帖子,順便說下個人的意見:

需求是這樣的 ,對下面需求做重構:

bob is a lackadaisical teenager. in conversation, his responses are very limited.

bob answers 'sure.' if you ask him a question.

he answers 'whatever.' if you tell him something.

he answers 'woah, chill out!' if you yell at him (all caps).

he says 'fine. be that way!' if you address him without actually saying anything.

from ruby-china  **:

有一下幾種做法:

1.典型的if else判斷的 :

class bob

def hey(words)

if words.nil? || words.strip.empty?

"fine. be that way!"

elsif words.upcase == words

"woah, chill out!"

elsif words[-1] == "?"

"sure."

else

"whatever."

endend

end

2,將if else 部分抽出

class wordsparser

def silent?(words)

words.nil? || words.strip.empty?

enddef shout?(words)

words.upcase == words

enddef question?(words)

words.end_with?("?")

endendclass bob

def hey(words)

@parser = wordsparser.new

if @parser.silent?(words)

"fine. be that way!"

elsif @parser.shout?(words)

"woah, chill out!"

elsif @parser.question?(words)

"sure."

else

"whatever."

endend

end

還有一位做的更加簡潔的,我也和喜歡 :

class bob

def hey(words)

return "fine. be that way!" if words.nil? || words.strip.empty?

return "woah, chill out!" if words.upcase == words

return "sure" if words[-1] == "?"

return "whatever."

endend

3但是我最喜歡的還是下面這種 :

class bob

rules = [

[->w, 'fine. be that way!'],

[->w, 'woah, chill out!' ],

[->w, 'sure.' ],

[->w, 'whatever.' ]

] def hey(words)

rules.each

endend

也許你看不出來為什麼我最喜歡第三種,但是稍微分析下就發現第三種做法的好處。先不說你能不能看懂lambda表示式,他整體的這樣設計就是一種更容易擴充套件的做法。舉個例子來說:現在我新增一種新的功能

bob answers 'hello world.' if you tell him a programming language . 

那會有怎麼樣的做法呢?

對於第1種:新增乙個elsif 來滿足這樣的需求 

對於第2種:在wordsparser裡面新增乙個ifelse 還要在bob裡面新增乙個ifelse

對於第3種: 新增乙個lumbda表達語句就好了。

下面詳細的說下前兩種的不好。

對於第1種來說,當年的需求種類少的話,還好說,多幾個ifelse就好了。但是當需求大的時候呢,這乙個函式裡面充滿了ifelse(不要笑,我見過乙個類裡面只有兩個函式乙個幾行的函式,另外乙個則都是ifelse)。這時候你會發現他比較大了。應該說可以把他抽成乙個模組了。這時候你在去做,可能形成的就是第2種的樣式。

對於第2種來說,其實已經很不錯了,但是有乙個設計原則他卻違反了,那就是ocp(open-close-principle),不知道你有沒有發現,你每新增一項功能的時候都會修改兩個地方,乙個是重構出去的函式裡面新增乙個ifelse。還有在bob裡面新增乙個ifelse。ocp所說的就是對修改關閉,對擴充套件開放。所以來說第三種就是最合適的了。

你可以想象一下。如果擴充功能的話,對於第三種來說是多麼的方便。當然在第3種方案裡面可以將rules抽出來作為乙個擴充套件功能類。作為expression的子類。

最後說一下,有人可能說他本來就懶你還讓他做這麼多。意思是:使用者就這些需求,沒有必要擴充套件,我只能說,我想多了。哈哈。。

由一道試題想到的

前段時間忙著換工作,面試了幾家公司,其中有些筆試題,蠻有意思的,給我很大啟發。最好玩的一道程式設計題 不使用中間變數,交換2個int型變數a和b的值。寫出方法。這個其實不是很難,方法如下 public class exchange void swap int a int b 給我的啟發是,在程式設計...

由乙個網域名稱想到的

花了 大價錢 買了乙個網域名稱 zzm.hk,夠短了,其實沒有什麼含義,但沒有其它選擇。這樣的網域名稱,好像只能指向個人部落格站點,或者用qq郵箱體系裡的網域名稱郵箱功能設定乙個如 i zzm.hk 記得給我發郵件 的個人email。記得 phpdragon 以前還註冊過乙個 phpdragon.c...

由解乙個bug想到的

最近花費了很久時間去解決乙個bug,在我手裡有乙個月了。今天同事出手幫忙解決掉了,分外感激。這個bug如果按照我的思路,再過乙個月也不一定能夠解決掉。三人行,必有我師。同事身上有許多值得我學習的地方。比如,我是從程式碼執行機制方面找尋產生bug的原因,可是程式碼數量龐大。很難發現其中的某一處問題所在...