OOP设计思考——何时使用接口?
一、“接口”初步:
從OOP設(shè)計(jì)角度來(lái)分析,“接口”是一個(gè)很特殊的“類(lèi)”,特殊之處在于:
1)不能為接口中定義的方法添加關(guān)鍵字(只允許是public)。
2)可以定義事件/方法/屬性,但都無(wú)法實(shí)現(xiàn)(只能讓實(shí)現(xiàn)類(lèi)去實(shí)現(xiàn))。
以上這些限制了接口的應(yīng)用范圍——意味著接口只是作為一個(gè)對(duì)類(lèi)的契約而存在,談不上“代碼復(fù)用”(因?yàn)榻涌谧陨聿荒芏x方法,自然實(shí)現(xiàn)類(lèi)無(wú)法調(diào)用它們,也就不構(gòu)成重載/重寫(xiě)的概念了),也根本不存在“繼承”的概念。因此“接口”的關(guān)鍵字是Implement而不是Inherit(在C#中則都是英文狀態(tài)的冒號(hào))。
由接口自身的定義,我們聯(lián)想到最簡(jiǎn)單的接口應(yīng)用就是強(qiáng)制某個(gè)類(lèi)必須具備某種方法,譬如說(shuō)我要設(shè)計(jì)一個(gè)圍棋程序,其中的“棋子”如果是一個(gè)類(lèi),那么星羅密布的圍棋子其實(shí)都是自身的拷貝和翻版,因此我可以實(shí)現(xiàn)NET自帶的IClonable類(lèi);又如NET自帶的數(shù)據(jù)庫(kù)類(lèi)中由于需要消耗大量?jī)?nèi)存和磁盤(pán)開(kāi)銷(xiāo),因此及時(shí)釋放內(nèi)存很有必要;此時(shí)我們可以實(shí)現(xiàn)IDispose接口來(lái)強(qiáng)制讓這個(gè)類(lèi)帶有Dispose方法,用于銷(xiāo)毀內(nèi)部消耗大量資源的托管和非托管組件和實(shí)例等東西。
其次,實(shí)現(xiàn)了一個(gè)特定接口的類(lèi)可以通過(guò)接口來(lái)調(diào)用。這就意味著對(duì)于客戶端而言,無(wú)需知道接口內(nèi)具體方法是如何實(shí)現(xiàn)的,只要知道能夠?qū)崿F(xiàn)這個(gè)效果是哪個(gè)類(lèi),直接用接口引用這個(gè)類(lèi)的實(shí)體就可以了。這就是我們所謂的“面向接口編程”。NET一些特定場(chǎng)景下大量使用到接口,譬如最典型的泛型List中Sort方法就是傳入一個(gè)實(shí)現(xiàn)了IComparer<T>的接口——只要你把實(shí)現(xiàn)了這個(gè)接口的實(shí)例當(dāng)成參數(shù)傳入到此方法中,則Sort內(nèi)部自動(dòng)調(diào)用你的方法排序,相對(duì)于NET類(lèi)庫(kù)而言方法是黑箱的:它只需要結(jié)果,根本不關(guān)心過(guò)程。這種“屏蔽實(shí)現(xiàn)端,讓客戶只知道該知道的東西的”的設(shè)計(jì)理念還廣泛地應(yīng)用于各類(lèi)OOP設(shè)計(jì)模式中——比如工廠模式,適配器模式等。
讓子類(lèi)去實(shí)現(xiàn)具體方法并非“接口”之專(zhuān)利,“抽象類(lèi)”的abstract方法也是延時(shí)實(shí)現(xiàn)。那么它們有何區(qū)別呢?
二、“接口”VS“抽象類(lèi)”:
這個(gè)題目簡(jiǎn)直每次面試都被問(wèn)及,但要真正說(shuō)清楚它們的區(qū)別還真的非常不容易!前面已經(jīng)說(shuō)過(guò)——抽象類(lèi)是類(lèi)的抽象表述(不可實(shí)例化,一般具備一個(gè)或多個(gè)abstract方法讓子類(lèi)去實(shí)現(xiàn)),因此抽象類(lèi)主要的作用在于盡可能提高“代碼復(fù)用”(包括方法繼承以及方法重載/重寫(xiě)),而且一個(gè)抽象類(lèi)往往衍生出多個(gè)具備相似功能的子類(lèi),因而抽象類(lèi)是衍生其它一系列類(lèi)的通用模板。
相比較而言接口非常單純,“城府”遠(yuǎn)沒(méi)有“抽象類(lèi)”那么“深”:簡(jiǎn)而言之,接口作用只是讓某個(gè)類(lèi)擁有某個(gè)方法,這個(gè)方法是對(duì)外公開(kāi)暴露的,也就是可以為其它擁有該接口的類(lèi)隨意調(diào)用,可以使得兩個(gè)毫不相干的類(lèi)在不引用的情況下發(fā)生特殊的關(guān)系——最經(jīng)典的例子莫過(guò)于“設(shè)計(jì)模式”中的“觀察者模式”,微軟由此基礎(chǔ)上發(fā)展出“事件”來(lái)取代這種模式,但是它的的確確是“事件”的開(kāi)山鼻祖。
同時(shí),抽象類(lèi)衍生出的子類(lèi)必然具備抽象類(lèi)允許繼承的全部方法(即便是重寫(xiě)!),但是有時(shí)并不都是需要這些方法時(shí)(比如通過(guò)“鴨子工廠”介紹策略模式就是一個(gè)典型),接口往往可以把變化的方法和不變的隔離,達(dá)到動(dòng)態(tài)的效果。
談到策略模式,其實(shí)“策略模式”的本質(zhì)是通過(guò)一個(gè)基本的策略工具衍生出若干個(gè)相關(guān)的策略算法,然后在其它類(lèi)中引用“策略工具”,由不同實(shí)現(xiàn)該工具的“策略算法”決定如何進(jìn)行策略的一種設(shè)計(jì)模式。“策略工具”如果說(shuō)只是一個(gè)單純的“算法”,那么完全可以使用接口;如果是一個(gè)復(fù)雜的,乃至這個(gè)“策略工具”可以派生出大量類(lèi)似的“策略算法”的,優(yōu)先考慮的是抽象類(lèi)而不是接口。
轉(zhuǎn)載于:https://www.cnblogs.com/ServiceboyNew/archive/2012/11/19/2775779.html
總結(jié)
以上是生活随笔為你收集整理的OOP设计思考——何时使用接口?的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: The RSpec Book笔记《一》初
- 下一篇: JEECMS模板