一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

腳本之家,腳本語言編程技術(shù)及教程分享平臺!
分類導(dǎo)航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服務(wù)器之家 - 腳本之家 - Ruby - 設(shè)計模式中的模板方法模式在Ruby中的應(yīng)用實例兩則

設(shè)計模式中的模板方法模式在Ruby中的應(yīng)用實例兩則

2020-05-07 11:15guolin Ruby

這篇文章主要介紹了設(shè)計模式中的模板方法模式在Ruby中的應(yīng)用實例兩則,經(jīng)典的項目經(jīng)理例子在這里又被套上用了^^需要的朋友可以參考下

實例一
今天你還是像往常一樣來上班,一如既往地開始了你的編程工作。
項目經(jīng)理告訴你,今天想在服務(wù)器端增加一個新功能,希望寫一個方法,能對Book對象進(jìn)行處理,將Book對象的所有字段以XML格式進(jìn)行包裝,這樣以后可以方便與客戶端進(jìn)行交互。并且在包裝開始前和結(jié)束后要打印日志,這樣方便調(diào)試和問題定位。
沒問題!你覺得這個功能簡直是小菜一碟,非常自信地開始寫起代碼。
Book對象代碼如下:

?
1
2
3
class Book
 attr_accessor :book_name, :pages, :price, :author, :isbn
end

然后寫一個類專門用于將Book對象包裝成XML格式:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Formatter
 
 def format_book(book)
  puts "format begins"
  result = "<book_name>#{book.book_name}</book_name>\n"
  result += "<pages>#{book.pages}</pages>\n"
  result += "<price>#{book.price}</price>\n"
  result += "<author>#{book.author}</author>\n"
  result += "<isbn>#{book.isbn}</isbn>\n"
  puts "format finished"
  result
 end
 
end

 
調(diào)用代碼如下:

?
1
2
3
4
5
6
7
8
9
book = Book.new
book.book_name = "Programming Ruby"
book.pages = 830
book.price = 45
book.author = "Dave Thomas"
book.isbn = "9787121038150"
formatter = Formatter.new
result = formatter.format_book(book)
puts result

你寫好了之后,迫不及待地開始運(yùn)行,運(yùn)行結(jié)果也完全符合你的期望。

設(shè)計模式中的模板方法模式在Ruby中的應(yīng)用實例兩則

項目經(jīng)理看完后,對你非常滿意,小伙效率很高的嘛!你也非常的得意。
不過兩天之后,項目經(jīng)理又找到了你,他說之前沒有考慮到需要交互的客戶端還包括手機(jī)設(shè)備,而手機(jī)設(shè)備都比較吃流量,用XML格式來傳輸太耗流量了,想最好能改成使用JSON格式傳輸。但是之前的XML格式也要保留,最好可以由客戶端指定使用哪種格式。
你有些不開心,心里低估著,為什么一開始不考慮周全呢,現(xiàn)在又要改遺留代碼。但對方畢竟是領(lǐng)導(dǎo),你還是要服從命令的,于是你開始修改Formatter類:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Formatter
 
 def format_book(book, format)
  puts "format begins"
  result = ""
  if format == :xml
   result += "<book_name>#{book.book_name}</book_name>\n"
   result += "<pages>#{book.pages}</pages>\n"
   result += "<price>#{book.price}</price>\n"
   result += "<author>#{book.author}</author>\n"
   result += "<isbn>#{book.isbn}</isbn>\n"
  elsif format == :json
   result += "{\n"
   result += "\"book_name\" : \"#{book.book_name}\",\n"
   result += "\"pages\" : \"#{book.pages}\",\n"
   result += "\"price\" : \"#{book.price}\",\n"
   result += "\"author\" : \"#{book.author}\",\n"
   result += "\"isbn\" : \"#{book.isbn}\",\n"
   result += '}'
  end
  puts "format finished"
  result
 end
 
end

調(diào)用代碼如下:

?
1
2
3
4
5
6
7
8
9
10
11
book = Book.new
book.book_name = "Programming Ruby"
book.pages = 830
book.price = 45
book.author = "Dave Thomas"
book.isbn = "9787121038150"
formatter = Formatter.new
result = formatter.format_book(book, :xml)
puts result
result = formatter.format_book(book, :json)
puts result

再次運(yùn)行程序,得到了以下結(jié)果。

設(shè)計模式中的模板方法模式在Ruby中的應(yīng)用實例兩則

項目經(jīng)理看到運(yùn)行結(jié)果后開心地說:“太好了,這正是我想要的!”
可是你這次卻沒有那么開心,你覺得代碼已經(jīng)有些混亂了,XML格式的邏輯和JSON格式的邏輯混淆在一起,非常不利于閱讀,而且如果以后還需要擴(kuò)展功能也會非常困難。好在傳輸格式一般也就XML和JSON了,應(yīng)該不會再有什么擴(kuò)展了,你這樣安慰自己道。
但幻想總會被現(xiàn)實打破,“我最近聽說有個YAML格式挺好玩的.......” 項目經(jīng)理說道。這個時候你已經(jīng)有想打人的沖動了!!!

很多時候就是這樣,在公司里寫的代碼亂七八糟,質(zhì)量極差,很大一部分原因就是因為需求變來變?nèi)ァN覀儾粩嘣谠写a基礎(chǔ)上補(bǔ)充各種后續(xù)加入的情況,在一行行新增的if語句下面,我們的代碼變得不堪入目。當(dāng)然,我們作為程序員,對于需求這種東西沒有太多的話語權(quán),在這方面我們無能為力。但是我們可以盡量地把程序的架構(gòu)設(shè)計好,讓我們寫出的代碼更具有擴(kuò)展性,這樣就可以應(yīng)對各種需求變更了。

下面你將要使用23種設(shè)計模式中的模板方法來改進(jìn)以上程序。
首先要定義專門的子類來處理每種傳輸格式的具體邏輯,這樣不同傳輸格式的邏輯可以從一個方法里分離開,明顯便于閱讀和理解。
定義類XMLFormatter繼承自Formatter,里面加入處理XML格式的具體邏輯:

?
1
2
3
4
5
6
7
8
9
10
11
class XMLFormatter < Formatter
 
 def formating(book)
  result = "<book_name>#{book.book_name}</book_name>\n"
  result += "<pages>#{book.pages}</pages>\n"
  result += "<price>#{book.price}</price>\n"
  result += "<author>#{book.author}</author>\n"
  result += "<isbn>#{book.isbn}</isbn>\n"
 end
 
end

定義類JSONFormatter繼承自Formatter,里面加入處理JSON格式的具體邏輯:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
class JSONFormatter < Formatter
  
 def formating(book)
  result = "{\n"
  result += "\"book_name\" : \"#{book.book_name}\",\n"
  result += "\"pages\" : \"#{book.pages}\",\n"
  result += "\"price\" : \"#{book.price}\",\n"
  result += "\"author\" : \"#{book.author}\",\n"
  result += "\"isbn\" : \"#{book.isbn}\",\n"
  result += '}'
 end
  
end

然后將Formatter中的代碼進(jìn)行修改,如下所示:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Formatter
 
 def format_book(book)
  before_format
  result = formating(book)
  after_format
  result
 end
  
 def before_format
  puts "format begins"
 end
  
 def formating(book)
  raise "You should override this method in subclass."
 end
  
 def after_format
  puts "format finished"
 end
 
end

你會發(fā)現(xiàn)format_book方法只有四步,第一步調(diào)用before_format,去打印格式轉(zhuǎn)換前的日志。第二步調(diào)用formating,處理具體的轉(zhuǎn)換邏輯,但是formating方法中只是raise了一個異常,因為具體的轉(zhuǎn)換的邏輯應(yīng)該由子類來處理,如果走到了父類的formating方法中,就說明應(yīng)該出現(xiàn)異常。第三步調(diào)用after_format,去打印格式轉(zhuǎn)換后的日志。第四步返回result。
最后調(diào)用代碼如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
book = Book.new
book.book_name = "Programming Ruby"
book.pages = 830
book.price = 45
book.author = "Dave Thomas"
book.isbn = "9787121038150"
xmlFormatter = XMLFormatter.new
result = xmlFormatter.format_book(book)
puts result
jsonFormatter = JSONFormatter.new
result = jsonFormatter.format_book(book)
puts result

運(yùn)行之后,你會發(fā)現(xiàn)運(yùn)行結(jié)果和修改前代碼的運(yùn)行結(jié)果完全相同。但是使用模板方法之后,代碼的可讀性有了很大的提高,因為處理格式轉(zhuǎn)換的代碼都放到了各自的類當(dāng)中,而不是全部塞進(jìn)一個方法中。并且在擴(kuò)展性上也有了很大的提升,比如你開始感興趣項目經(jīng)理說的YAML格式了。
定義類YAMLFormatter繼承自Formatter,里面加入處理YAML格式的具體邏輯:

?
1
2
3
4
5
6
7
8
9
10
11
class YAMLFormatter < Formatter
 
 def formating(book)
  result = "book_name: #{book.book_name}\n"
  result += "pages: #{book.pages}\n"
  result += "price: #{book.price}\n"
  result += "author: #{book.author}\n"
  result += "isbn: #{book.isbn}\n"
 end
 
end

調(diào)用代碼只需要加入:

?
1
2
3
yamlFormatter = YAMLFormatter.new
result = yamlFormatter.format_book(book)
puts result

好了,令人頭疼的YAML格式就這樣被支持了,只需要在調(diào)用的時候決定是實例化XMLFormatter,JSONFormatter還是YAMLFormatter,就可以按照相應(yīng)的規(guī)格進(jìn)行格式轉(zhuǎn)換了。而且整體的代碼很有條理,看起來也很舒心。這個時候,你會輕松地向項目經(jīng)理調(diào)侃一句,還有需要支持的格式嗎?

 

實例二

 

需求:

學(xué)生抄題目,做題目

初始代碼

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# -*- encoding: utf-8 -*-
 
#學(xué)生甲的試卷類
class TestPaperA
 
 def question1
  puts '楊過得到,后來給了郭靖,煉成倚天劍,屠龍刀的玄鐵可能是[] a.球墨鑄鐵 b.馬口鐵 c.高速合金鋼 d.碳塑纖維 '
  puts '答案:b'
 end
 
 def question2
  puts '楊過、程英、陸無雙鏟除了情花,造成了[] a.使這種植物不再害人 b.使一種珍稀物種滅絕 c.破壞了那個生物圈的生態(tài)平衡 d.造成該地區(qū)沙漠化 '
  puts '答案:a'
 end
 
 def question3
  puts '藍(lán)鳳凰的致使華山師徒、桃谷六仙嘔吐不止,如果你是大夫,會給他們開什么藥[] a.阿司匹林 b.牛黃解毒片 c.氟酸 d.讓他們喝大量的生牛奶 e.以上全不對'
  puts '答案:c'
 end
 
end
#學(xué)生乙的試卷類
class TestPaperB
 
 def question1
  puts '楊過得到,后來給了郭靖,煉成倚天劍,屠龍刀的玄鐵可能是[] a.球墨鑄鐵 b.馬口鐵 c.高速合金鋼 d.碳塑纖維 '
  puts '答案:d'
 end
 
 def question2
  puts '楊過、程英、陸無雙鏟除了情花,造成了[] a.使這種植物不再害人 b.使一種珍稀物種滅絕 c.破壞了那個生物圈的生態(tài)平衡 d.造成該地區(qū)沙漠化 '
  puts '答案:b'
 end
 
 def question3
  puts '藍(lán)鳳凰的致使華山師徒、桃谷六仙嘔吐不止,如果你是大夫,會給他們開什么藥[] a.阿司匹林 b.牛黃解毒片 c.氟酸 d.讓他們喝大量的生牛奶 e.以上全不對'
  puts '答案:a'
 end
 
end
puts '學(xué)生甲抄的試卷'
student1 = TestPaperA.new
student1.question1
student1.question2
student1.question3
 
puts '學(xué)生乙抄的試卷'
student2 = TestPaperB.new
student2.question1
student2.question2
student2.question3

存在的問題:

TestPaperA和TestPaperB中的代碼很多相同的地方,不利于維護(hù),如果需要修改題目的話,就要改兩處
改后的代碼

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# -*- encoding: utf-8 -*-
 
class TestPaper
 def question1
  puts '楊過得到,后來給了郭靖,煉成倚天劍,屠龍刀的玄鐵可能是[] a.球墨鑄鐵 b.馬口鐵 c.高速合金鋼 d.碳塑纖維 '
 end
 
 def question2
  puts '楊過、程英、陸無雙鏟除了情花,造成了[] a.使這種植物不再害人 b.使一種珍稀物種滅絕 c.破壞了那個生物圈的生態(tài)平衡 d.造成該地區(qū)沙漠化 '
 end
 
 def question3
  puts '藍(lán)鳳凰的致使華山師徒、桃谷六仙嘔吐不止,如果你是大夫,會給他們開什么藥[] a.阿司匹林 b.牛黃解毒片 c.氟酸 d.讓他們喝大量的生牛奶 e.以上全不對'
 end
end
 
#學(xué)生甲的試卷類
class TestPaperA < TestPaper
 
 def question1
  super
  puts '答案:b'
 end
 
 def question2
  super
  puts '答案:a'
 end
 
 def question3
  super
  puts '答案:c'
 end
 
end
#學(xué)生乙的試卷類
class TestPaperB < TestPaper
 
 def question1
  super
  puts '答案:d'
 end
 
 def question2
  super
  puts '答案:b'
 end
 
 def question3
  super
  puts '答案:a'
 end
 
end
puts '學(xué)生甲抄的試卷'
student1 = TestPaperA.new
student1.question1
student1.question2
student1.question3
 
puts '學(xué)生乙抄的試卷'
student2 = TestPaperB.new
student2.question1
student2.question2
student2.question3

可以看出,抽取出來一個公共的試卷類,讓甲乙去繼承,公用其中的試題。這時再看TestPaperA和TestPaperB,不同的只有答案a、b、c、d不一樣,其他的都一樣。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# -*- encoding: utf-8 -*-
 
class TestPaper
 def question1
  puts '楊過得到,后來給了郭靖,煉成倚天劍,屠龍刀的玄鐵可能是[] a.球墨鑄鐵 b.馬口鐵 c.高速合金鋼 d.碳塑纖維 '
  puts "答案:#{answer1}"
 end
 
 def question2
  puts '楊過、程英、陸無雙鏟除了情花,造成了[] a.使這種植物不再害人 b.使一種珍稀物種滅絕 c.破壞了那個生物圈的生態(tài)平衡 d.造成該地區(qū)沙漠化 '
  puts "答案:#{answer2}"
 end
 
 def question3
  puts '藍(lán)鳳凰的致使華山師徒、桃谷六仙嘔吐不止,如果你是大夫,會給他們開什么藥[] a.阿司匹林 b.牛黃解毒片 c.氟酸 d.讓他們喝大量的生牛奶 e.以上全不對'
  puts "答案:#{answer3}"
 end
 def answer1; end
 def answer2; end
 def answer3; end
end
 
#學(xué)生甲的試卷類
class TestPaperA < TestPaper
 
 def answer1
  'b'
 end
 
 def answer2
  'a'
 end
 
 def answer3
  'c'
 end
 
end
#學(xué)生乙的試卷類
class TestPaperB < TestPaper
 
 def answer1
  'd'
 end
 
 def answer2
  'b'
 end
 
 def answer3
  'a'
 end
 
end
puts '學(xué)生甲抄的試卷'
student1 = TestPaperA.new
student1.question1
student1.question2
student1.question3
 
puts '學(xué)生乙抄的試卷'
student2 = TestPaperB.new
student2.question1
student2.question2
student2.question3

這里將TestPaperA和TestPaperB中的答案抽離到了父類中,僅僅保存不同的部分。

父類成為子類的模板,所有重復(fù)的代碼都應(yīng)該上升到父類去,而不是讓每個子類都去重復(fù)。

當(dāng)我們要完成在某一細(xì)節(jié)層次一致的過程或一系列步驟,但其個別步驟在更詳細(xì)層次上的實現(xiàn)可能不同時,我們通常考慮使用模板方法模式來處理。

延伸 · 閱讀

精彩推薦
  • RubyRuby簡潔學(xué)習(xí)筆記(一):字符串、數(shù)字、類和對象

    Ruby簡潔學(xué)習(xí)筆記(一):字符串、數(shù)字、類和對象

    這篇文章主要介紹了Ruby簡潔學(xué)習(xí)筆記(一):字符串、數(shù)字、類和對象,本文是學(xué)習(xí)筆記第一篇,需要的朋友可以參考下 ...

    腳本之家2472020-04-20
  • RubyRuby環(huán)境下安裝使用bundler來管理多版本的gem

    Ruby環(huán)境下安裝使用bundler來管理多版本的gem

    這篇文章主要介紹了Ruby環(huán)境下安裝使用bundler來管理多版本的gem的方法,舉了Ruby On Rails中的應(yīng)用實例來進(jìn)行演示,需要的朋友可以參考下 ...

    日拱一卒4332020-05-10
  • RubyRuby迭代器的7種技巧分享

    Ruby迭代器的7種技巧分享

    這篇文章主要介紹了Ruby迭代器的7種技巧分享,Ruby中的迭代器非常人性化,本文既是講解了7個技巧也是講解了7種迭代器,需要的朋友可以參考下 ...

    腳本之家4782020-04-20
  • RubyRuby進(jìn)行文件信息輸出實例代碼

    Ruby進(jìn)行文件信息輸出實例代碼

    Ruby進(jìn)行文件信息輸出實例代碼,數(shù)據(jù)是隨機(jī)的,所以每次的記錄都會不同。 ...

    ruby教程網(wǎng)2962020-04-10
  • RubyCentOS中配置Ruby on Rails環(huán)境

    CentOS中配置Ruby on Rails環(huán)境

    經(jīng)過一個上午的折騰,終于把ROR環(huán)境在CentOS中搞定,繞了很多彎路,把文章寫下來總結(jié)一下 ...

    可樂加糖4762020-04-12
  • Ruby剖析 Ruby 訪問控制

    剖析 Ruby 訪問控制

    前面,我們說 Ruby 沒有函數(shù),只有方法.而且實際上有不止一種方法.這一節(jié)我們介紹 訪問控制 (accesscontrols). 想想當(dāng)我們在最高層而不是在一個類的定義里定義...

    ruby教程網(wǎng)3572020-04-08
  • RubyRuby設(shè)計模式編程中使用Builder建造者模式的實例

    Ruby設(shè)計模式編程中使用Builder建造者模式的實例

    這篇文章主要介紹了Ruby設(shè)計模式編程中使用Builder建造者模式的實例,建造者模式將一個復(fù)雜對象的構(gòu)造與它的表示分離,使同樣的構(gòu)建過程可以創(chuàng)建不同的表...

    范孝鵬2192020-05-07
  • Ruby簡要說明Ruby中的迭代器

    簡要說明Ruby中的迭代器

    這篇文章主要介紹了Ruby中的迭代器,迭代器的概念在動態(tài)語言的編程中十分重要,文章中介紹了Ruby中的each迭代器和collect迭代器,需要的朋友可以參考下 ...

    goldensun2772020-04-25
主站蜘蛛池模板: 8x8x极品国产在线 | 天堂精品高清1区2区3区 | 亚洲精品色图 | 日本高清中文 | 国产精品短视频 | 国产永久免费视频m3u8 | 精品免费久久久久久影院 | 我的奶头被客人吸的又肿又红 | 国产一区二区精品久久 | 新影音先锋男人色资源网 | 喷潮女王cytherea全部视频 | 免费的毛片视频 | 天天视频官网天天视频在线 | 楚乔传第二部免费播放电视连续剧 | 免费精品一区二区三区在线观看 | 午夜精品久视频在线观看 | 极品丝袜乱系列在线阅读 | 婷婷在线观看香蕉五月天 | h肉动漫在线视频无修无遮挡 | 催眠白丝舞蹈老师小说 | 77成人影视 | 欧美不卡一区二区三区免 | 亚洲精品欧洲久久婷婷99 | 久草在线草a免费线看 | 国产亚洲人成网站天堂岛 | 91欧美国产 | 国产亚洲精品91 | 欧美成人禁片在线观看俄罗斯 | 女人把扒开给男人爽的 | 亚洲v日韩v欧美在线观看 | 护士让我吃奶我扒她奶 | 久久综合老色鬼网站 | 国产女主播在线播放一区二区 | 国产成人愉拍免费视频 | 吉泽明步高清无码中文 | 亚洲天堂精品在线观看 | 牛人国产偷窥女洗浴在线观看 | 我的奶头被客人吸的又肿又红 | 亚洲AV福利天堂一区二区三 | 色悠久久久久综合网小说 | 成人影院vs一区二区 |