成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

繼承是代碼復用的最佳方案嗎?

開發 前端
代碼復用,很多人覺得繼承就是絕佳方案。若把繼承理解成代碼復用,更多是站在子類角度向上看。在客戶端代碼使用時,面對的是子類,這種繼承叫實現繼承。

繼承,一個父類可有許多個子類。父類就是把一些公共代碼放進去,之后在實現其他子類時,少寫一些代碼。

代碼復用,很多人覺得繼承就是絕佳方案。若把繼承理解成代碼復用,更多是站在子類角度向上看。在客戶端代碼使用時,面對的是子類,這種繼承叫實現繼承:

Child object = new Child();

還有一種看待繼承的角度:從父類往下看,客戶端使用時,面對的是父類,這種繼承叫接口繼承:

Parent object = new Child();

但接口繼承更多和多態相關。本文主要討論實現繼承。

不推薦實現繼承:

? 繼承很寶貴,Java只支持單繼承 一個類只能有一個父類,一旦繼承的位置被實現繼承占據,再想做接口繼承就難了

? 實現繼承通常也是一種受程序設計語言局限的思維方式 很多語言,不使用繼承,也有代碼復用方案

1、案例

產品報表服務,其中的某服務:查詢產品信息。該查詢過程通用,別的服務也可用。所以,我把它放父類以復用:

class BaseService {
// 獲取相應產品信息
protected List<Product> getProducts(List<String> product) {
...
}
}

// 生成報表服務
class ReportService extends BaseService {
public void report() {
List<Product> product = getProduct(...);
// 生成報表
...
}
}

ReportService沒有繼承任何類,但也可復用代碼,即ProductFetcher模塊。這樣,若我需要有個獲取產品信息的地方,它不必非得是個服務,我無需繼承任何類。

獲取產品信息、生成報表是兩件事,只是因為在生成報表過程,需要獲取產品信息,所以,它有個基類。

不用繼承的實現:

class ProductFetcher {
// 獲取相應的產品信息
public List<Product> getProducts(List<String> product) {
...
}
}

// 生成報表服務
class ReportService {

private ProductFetcher fetcher;

public void report() {
List<Product> product = fetcher.getProducts(...);
// 生成報表
...
}
}

這就是組合:ReportService里組合一個ProductFetcher。設計通用原則:組合優于繼承。即若一個方案既能用組合實現,也能用繼承實現,那就用組合。

所以,要寫繼承以實現代碼復用時,問問自己,這是接口繼承,還是實現繼承?若是實現繼承,是不是可以寫成組合?

2、面向組合編程

可以組合的根因:獲取產品信息、生成報表服務本是兩件事(分離關注點)。你要是看出是兩件事了,就不會把它們放一起。

分解是設計的第一步,分解粒度越小越好。當可分解出多個關注點,每個關注點就是個獨立類。最終類由這一個個小類組合而得,即面向組合編程。按面向組合思維:為增加復雜度,增加一個報表生成器(ReportGenerator),在獲取產品信息后,生成報表:

class ReportService {

private ProductFetcher fetcher;

private ReportGenerator generator;

public void report() {
List<Product> product = fetcher.getProducts(...);
// 生成報表
generator.generate(product);
}
}

OOP面向的是“對象”,不是類!很多程序員習慣把對象理解成類的附屬品,但在Alan Kay的理解中,對象本身就是獨立個體。所以,有些語言支持直接在對象操作。

現在,想給報表服務新增接口:處理產品信息。這樣的處理只會影響這里的一個對象,而同樣是這個ReportService的其他實例,則完全不受影響。

  • ? 好處 不必寫那么多類,根據需要,在程序運行時組合出不同對象。

Java只有類這種組織方式,所以,很多有差異的概念只能用類這一個概念表示,思維受到限制,不同語言則提供不同的表現形式,讓概念更加清晰。

前面只是面向組合編程在思考方式的轉變,現在看設計差異。

3 案例

字體類(Font)需求:支持加粗、下劃線、斜體(Italic),且能任意組合。

3.1 繼承

需8個類:

圖片

3.2 組合

字體類(Font)只需三個獨立維度:是否加粗、下劃線、斜體。若再來一種需求,變成4種,采用繼承,類數量膨脹到16個,而組合只需再增加一個維度。把一個M*N問題,設計轉成M+N。

Java在面向組合編程方面能力較弱,但Java在嘗試不同方案。早期嘗試有Qi4j,后來Java 8加入default method,在一定程度上也可支持面向組合編程。

4、DCI

繼承是OOP原則之一,但編碼實踐中能用組合盡量使用組合。DCI也是一種編碼規范,對OOP的一種補充,核心思想也是關注點分離。

DCI是對象的Data數據, 對象使用的Context場景, 對象的Interaction交互行為三者簡稱, 是一種特別關注行為的模式(可對應GoF行為模式),而MVC模式是一種結構性模式,DCI可使用演員場景表演來解釋,某實體在某場景中扮演包公,實施包公升堂行為;典型事例是銀行帳戶轉帳,轉帳這行為按DDD很難劃分到帳號對象,它是跨兩個帳號實例之間的行為,可看成是帳號這個實體(PPT,見四色原型)在轉帳這個場景,實施了鈔票劃轉行為,這種新角度更貼近需求和自然,結合四色原型 DDD和DCI可以一步到位將需求更快地分解落實為可運行的代碼,是國際上軟件領域的一場革命。摘自 https://www.jdon.com/dci.html

5、總結

組合優于繼承。 復用方式背后的編程思想:面向組合編程。它給我們提供了一個不同的視角,但支撐面向組合編程的是分離關注點。將不同關注點分離,每個關注點成為一個模塊,在需要時組裝。面向組合編程,在設計本身上有很多優秀地方,可降低程序復雜度,更是思維轉變。

參考

? https://www.infoq.cn/article/2007/11/qi4j-intro

? https://en.wikipedia.org/wiki/Data,_context_and_interaction

責任編輯:武曉燕 來源: JavaEdge
相關推薦

2022-07-01 16:02:36

開源安全

2014-11-11 10:39:13

2013-03-14 09:33:14

遺留應用公有云云計算

2017-07-04 15:12:51

智慧城市PPP

2023-12-04 15:07:25

2023-11-02 12:48:00

游戲規則Flutter

2012-03-07 09:02:29

代碼復用

2014-07-22 09:08:40

2016-02-23 09:09:55

2015-08-24 15:36:48

數據中心

2022-10-27 15:08:16

物聯網智能建筑綠色建筑

2023-08-26 20:51:25

Python函數代碼

2023-04-12 11:36:07

波分復用WDM

2022-12-06 17:02:10

機器學習模型設置

2024-11-01 15:33:04

2017-12-19 15:20:47

代碼應用架構

2012-09-18 10:48:47

服務器虛擬化Hypervisor虛擬化

2024-05-31 09:50:21

2010-06-17 22:16:48

2009-01-09 22:52:16

服務器硬盤Linux
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 午夜av电影 | 四虎永久免费影院 | 第一福利社区1024 | 欧美亚洲成人网 | 欧美日韩高清 | 97色伦网| 欧美精品中文字幕久久二区 | 国产激情在线 | 婷婷桃色网 | 国产目拍亚洲精品99久久精品 | 韩日有码 | 日韩中文字幕网 | 国产一区二区三区在线看 | 日韩视频福利 | 在线中文字幕国产 | 精品国产欧美一区二区三区成人 | 精品中文在线 | 亚洲三级在线观看 | 国产农村一级国产农村 | 亚洲二区在线 | 亚洲一区二区av在线 | 精品久久久久久久久久久下田 | 成人无遮挡毛片免费看 | 羞羞的视频在线 | 中文字幕第一页在线 | 久久人体视频 | 欧美精品一区三区 | 日韩欧美国产一区二区三区 | 亚洲综合无码一区二区 | 国产一区二区三区在线 | 国产在线视频一区 | 亚洲精品www久久久久久广东 | 欧美精品一区二区在线观看 | 日韩精品一区二区三区视频播放 | 久久国产亚洲精品 | 欧美日韩在线一区二区 | av av在线 | 伊人一二三 | 成人精品一区二区三区中文字幕 | 国产成人免费视频 | 热99在线|