日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
面向“接口”編程和面向“實(shí)現(xiàn)”編程

如果你已經(jīng)讀了我的前幾篇關(guān)于面向?qū)ο蠓妒揭驗(yàn)槭艿絉ust and Go等語言的影響而發(fā)生變化的文章,看到了我正在研究的Rust設(shè)計(jì)模式,你會(huì)發(fā)現(xiàn)我對Rust語言十分的偏愛。

專注于為中小企業(yè)提供網(wǎng)站建設(shè)、成都網(wǎng)站制作服務(wù),電腦端+手機(jī)端+微信端的三站合一,更高效的管理,為中小企業(yè)曲水免費(fèi)做網(wǎng)站提供優(yōu)質(zhì)的服務(wù)。我們立足成都,凝聚了一批互聯(lián)網(wǎng)行業(yè)人才,有力地推動(dòng)了上千余家企業(yè)的穩(wěn)健成長,幫助中小企業(yè)通過網(wǎng)站建設(shè)實(shí)現(xiàn)規(guī)模擴(kuò)充和轉(zhuǎn)變。

除此之外,就在上周末,我讀完了經(jīng)典的《設(shè)計(jì)模式:可復(fù)用面向?qū)ο筌浖幕A(chǔ)》。這些種種,引起了我對這本書中談及的一個(gè)核心原則的思考:

面向‘接口’編程,而不是面向‘實(shí)現(xiàn)’。

這是什么意思?

首先我們需要理解什么是‘接口’,什么是‘實(shí)現(xiàn)’。簡言之,一個(gè)接口就是我們要調(diào)用的一系列方法的集合,有對象將會(huì)響應(yīng)這些方法調(diào)用。

一個(gè)實(shí)現(xiàn)就是為接口存放代碼和邏輯的地方。

本質(zhì)上講,這個(gè)原則倡導(dǎo)的是,當(dāng)我們寫一個(gè)函數(shù)或一個(gè)方法時(shí),我們應(yīng)該引用相應(yīng)的接口,而不是具體的實(shí)現(xiàn)類。

面向‘實(shí)現(xiàn)’編程

首先我們看看,如果不遵循這個(gè)原則會(huì)發(fā)生什么。

假設(shè)你是《華氏451度》這本書里的“Montag”這個(gè)人。大家都知道,書在華氏451度會(huì)燒著的。小說中的消防隊(duì)員只要看到了書就會(huì)把它們丟到火里。我們用面向?qū)ο蟮囊暯钦f問題,書有一個(gè)叫做burn()的方法。

書并不是唯一會(huì)燃燒的東西。假設(shè)我們還有另外一個(gè)東西,比如木頭,它也有一個(gè)方法叫做burn()。我們用Rust語言來寫這段代碼,看看在不是面向‘接口’編程的情況下它們是如何燃燒的。

 
 
 
  1. struct Book {
  2.     title: @str,
  3.     author: @str,
  4. }
  5. struct Log {
  6.     wood_type: @str,
  7. }

很直接。我們創(chuàng)建了兩個(gè)結(jié)構(gòu)體來表示一本書(Book)和一個(gè)木頭(Log)。下面我們?yōu)榻Y(jié)構(gòu)體實(shí)現(xiàn)它們的方法:

 
 
 
  1. impl Log {
  2.     fn burn(&self) {
  3.         println(fmt!("The %s log is burning!", self.wood_type));
  4.     }
  5. }
  6. impl Book {
  7.     fn burn(&self) {
  8.         println(fmt!("The book %s by %s is burning!", self.title, self.author));
  9.     }
  10. }

現(xiàn)在LogBook 都有了 burn() 方法,讓我們把它們放到火上。

我們首先把木頭放到火上:

 
 
 
  1. fn start_fire(lg: Log) {
  2.     lg.burn();
  3. }
  4. fn main() {
  5.     let lg = Log {
  6.         wood_type: @"Oak",
  7.         length: 1,
  8.     };
  9.     // Burn the oak log!
  10.     start_fire(lg);
  11. }

非常順利,我們得到了輸出 “The Oak log is burning!”.

現(xiàn)在,因?yàn)槲覀円呀?jīng)寫了一個(gè) start_fire 函數(shù),是否我們可以把書也傳進(jìn)去,因?yàn)樗鼈兌加?burn()。讓我們試一下:

 
 
 
  1. fn main() {
  2.     let book = Book {
  3.         title: @"The Brothers Karamazov",
  4.         author: @"Fyodor Dostoevsky",
  5.     };
  6.     // Let's try to burn the book...
  7.     start_fire(book);
  8. }

可行嗎?不行。出現(xiàn)了下面的錯(cuò)誤:

mismatched types: expected Log but found Book (expected struct Log but
found struct Book)

#p#

說的非常清楚,因?yàn)槲覀儗懗龅暮瘮?shù)需要的是一個(gè)Log結(jié)構(gòu)體,而不是我們傳進(jìn)去的 Book 結(jié)構(gòu)體。如何解決這個(gè)問題?我們可以再寫一個(gè)這樣的方法,把參數(shù)改成Book結(jié)構(gòu)體。然而,這并不是一個(gè)好的方案。我在兩個(gè)地方有了兩個(gè)幾乎一樣的函數(shù),如果一個(gè)修改,我們需要記得修改另外一個(gè)。

現(xiàn)在讓我們看看面向‘接口’編程如何能解決這個(gè)問題。

面向接口編程

我們?nèi)匀皇褂们懊娴慕Y(jié)構(gòu)體,但這次我們加一個(gè)接口。在Rust語言里,接口叫做traits

 
 
 
  1. struct Book {
  2.     title: @str,
  3.     author: @str,
  4. }
  5. struct Log {
  6.     wood_type: @str,
  7. }
  8. trait Burnable {
  9.     fn burn(&self);
  10. }

現(xiàn)在,除了兩個(gè)結(jié)構(gòu)體外,我們又多了一個(gè)叫做Burnable的接口。它的定義里只有一個(gè)叫做burn()的方法。我們來為每個(gè)結(jié)構(gòu)體實(shí)現(xiàn)它們的接口:

 
 
 
  1. impl Burnable for Log {
  2.     fn burn(&self) {
  3.         println(fmt!("The %s log is burning!", self.wood_type));
  4.     }
  5. }
  6. impl Burnable for Book {
  7.     fn burn(&self) {
  8.         println(fmt!("The book \"%s\" by %s is burning!", self.title, self.author));
  9.     }
  10. }

看起來并沒有多大的變化。這就是面向接口編程的強(qiáng)大之處:

 
 
 
  1. fn start_fire(item: T) {
  2.     item.burn();
  3. }

不僅僅只能接收一個(gè)Book對象或Log對象做參數(shù),我們可以往里面?zhèn)魅肴魏螌?shí)現(xiàn)了 Burnable 接口的類型(我們叫它類型T)。這使得我們的主函數(shù)可以寫成這樣:

 
 
 
  1. fn main() {
  2.     let lg = Log {
  3.         wood_type: @"Oak",
  4.     };
  5.     let book = Book {
  6.         title: @"The Brothers Karamazov",
  7.         author: @"Fyodor Dostoevsky",
  8.     };
  9.     // Burn the oak log!
  10.     start_fire(lg);
  11.     // Burn the book!
  12.     start_fire(book);
  13. }

正如期望的,我們得到了下面的輸出:

The Oak log is burning!

The book “The Brothers Karamazov” by Fyodor Dostoevsky is burning!

這跟我們期望的完全一致。

結(jié)論

遵循“面向‘接口’編程”原則,我們可以寫出一個(gè)函數(shù),使其能完全能復(fù)用任何實(shí)現(xiàn)了Burnable接口的對象。因?yàn)楹芏嗟某绦騿T都是按小時(shí)收費(fèi)的,我們寫出越多可復(fù)用的代碼,用于維護(hù)它們的時(shí)間就會(huì)越少,也就是更好。

因此,這是一個(gè)非常強(qiáng)大的編程思想。

并不是什么時(shí)候都可以面向接口編程的,但遵循這種原則會(huì)讓你更容易的寫出可復(fù)用的更優(yōu)雅的代碼。接口提供了非常優(yōu)秀的抽象歸納,讓我們的開發(fā)工作變得容易很多。

英文原文:Program to an Interface, Fool

譯文鏈接:http://www.aqee.net/program-to-an-interface-fool/


當(dāng)前名稱:面向“接口”編程和面向“實(shí)現(xiàn)”編程
網(wǎng)站路徑:http://www.dlmjj.cn/article/dhpjjes.html