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

Java開發(fā)者可以從Clojure借鑒的4樣?xùn)|西

開發(fā) 后端
Clojure當(dāng)然從Java借鑒了很多。如果能同時學(xué)習(xí)這兩門語言一定會很酷。下面是一些通用原則。事實上,這些原則在OOP的世界里眾所周知。你很可能已經(jīng)了解它們,所以本文不要求你學(xué)習(xí)Clojure,但是我推薦你去這么做。

我在大學(xué)時學(xué)的Java。OOP(即面向?qū)ο缶幊蹋┠P蜕钪苍谖业乃季S中。我想分享一些我從Clojure中學(xué)到的東西。

Clojure當(dāng)然從Java借鑒了很多。如果能同時學(xué)習(xí)這兩門語言一定會很酷。下面是一些通用原則。事實上,這些原則在OOP的世界里眾所周知。你很可能已經(jīng)了解它們,所以本文不要求你學(xué)習(xí)Clojure,但是我推薦你去這么做。

1、使用不變值

Clojure 得以聞名的一個特性是它的不可變的數(shù)據(jù)結(jié)構(gòu)(immutable data structures)。甚至在Java的早期,不變值也是一種很受歡迎的做法。String是不可變的,這點在Java剛發(fā)布那會備受爭議。在那時,C 和C++的字符串僅僅是可以改變的數(shù)組。不可變的String被認(rèn)為是低效的。但是,回頭再看,不可變的String似乎是一個正確的選擇。Java中的許多可變類現(xiàn)在被認(rèn)為是設(shè)計失誤。拿java.util.Date來說,改變一個日期的月份值有什么意思呢?

讓我們更深入地分析下。假設(shè)我是一個對象。你詢問我的生日。我給你一張紙,上面寫著我的生日是1981.7.18。你把這張紙帶回家,存在某個地方,甚至讓其他人看到這張紙。

其中有一個人看到這張紙上的日期后說“cool,a date!”,并且修改為他自己的生日:通過調(diào)用setTime方法修改為1976.4.2。這樣下一個問我生日的人得到的實際上是這個家伙的生日。這將是多么糟糕的一件事!我將后悔我將那張可以改變我生日的魔術(shù)紙給了別人。

讓值可變的導(dǎo)致這種magic-changing-at-a-distance行為常常可能發(fā)生。它之所以不當(dāng)?shù)囊粋€原因是它違反了信息隱藏原則。我的生日是我這個對象的部分狀態(tài)。如果我讓生日的月份、日期和年份可以直接被修改,那么我實際上是讓任何一個其他類都能夠直接訪問我的內(nèi)部狀態(tài)。

答案當(dāng)然不是使用setters。而是保證對象一旦構(gòu)建后不可變。這樣,我這個對象的內(nèi)部狀態(tài)就一直處于封裝狀態(tài)。

這也適用于集合。你讀過Iterator的文檔嗎?你能告訴我當(dāng)?shù)撞康膌ist改變時將發(fā)生什么?我也不能。一個不可變的list不應(yīng)該有這么一個復(fù)雜的接口。

解決方案:不要寫setter方法。對于集合,你有幾個可選方案。有一個簡單方案是使用Google Guava不可變類庫。如果不使用Guava,那么任何時候你需要返回一個集合時,先將集合拷貝一份,然后用java.util.Collections。unmodifiable()包裝一下這份拷貝,再扔掉對拷貝的引用。

  1. public static Map immutableMap(Map m) {  
  2.   return Collections.unmodifiableMap(new HashMap(m));  

2、不要在構(gòu)造函數(shù)中做多余的事情

設(shè)想這個場景:你的Person類有一個構(gòu)造函數(shù)接受一大堆信息(first name, last name,address等)并且將它們存為對象的狀態(tài)。你團隊中的某個人需要將這些數(shù)據(jù)存到文件中,比如存為JSON。為了方便創(chuàng)建Person對象,你增加了一個構(gòu)造函數(shù),接收inputStream參數(shù)并將其解析成JSON,然后設(shè)置對象狀態(tài)。你還增加了一個構(gòu)造函數(shù)接收aFile參數(shù),讀取文件并解析。之后又有一個人想從指定URL的web請求中讀取內(nèi)容,你又增加了一個構(gòu)造函數(shù)。非常棒!你現(xiàn)在有了一個非常方便的類。

但是稍等一下!Person類的職責(zé)是什么?最初它用來表示某個人的個人信息。現(xiàn)在它還負(fù)責(zé):

解析JSON

構(gòu)造Web請求

讀取文件

處理錯誤

而且現(xiàn)在Person類很難測試。我們?nèi)绾尾拍軠y試File構(gòu)造函數(shù)?首先,我們必須向文件系統(tǒng)中寫入一個臨時文件。不算太壞。那么我們?nèi)绾螠y試Web請求呢?設(shè)置一個Web服務(wù)器,配置Web服務(wù)器,然后調(diào)用構(gòu)造函數(shù)。

問題在于Person類違反了單一職責(zé)原則。Person類被用來保存狀態(tài)信息,而不是用來持久化存儲或者序列化的。它應(yīng)該是一個數(shù)據(jù)對象,而不應(yīng)該做更多的。

解決方案:避免讓構(gòu)造函數(shù)包含多余的邏輯。將“便利構(gòu)造函數(shù)”(比如上面解析JSON的構(gòu)造函數(shù))分離到靜態(tài)工廠方法。

3、針對小接口編程

Clojure做得非常好的一點是定義了一些功能強大的小接口,它們抽象出訪問模式。任何使用這個接口的函數(shù)可以使用實現(xiàn)這個接口的任何類型。任何新類型可以利用已有的功能。

拿Iterable接口來說,它泛化(或者抽象)了任何可以被順序訪問的對象(比如一個list或者一個set)。如果一個方法需要在某對象上順序操作,那么這個方法只需要了解那對象實現(xiàn)了Iterable接口。這就意味著,當(dāng)程序員寫程序時可以不必關(guān)注這個方法實際操作的對象的類型。

這符合依賴倒置原則,依賴倒置原則聲稱高層邏輯必需依賴于抽象而不是底層邏輯細(xì)節(jié)。接口很好的吻合了這條原則。高層邏輯應(yīng)該對接口操作,而底層邏輯實現(xiàn)接口。

解決方案:仔細(xì)思考類的訪問模式,看看能否抽象出小接口。然后針對接口編程。記住,有兩個地方會用到接口:實現(xiàn)接口者和調(diào)用者。

4、表達計算過程,而不僅僅是世界(Represent computation, not the world)

當(dāng)我讀大學(xué)時,老師告訴我們你們應(yīng)該用類來為現(xiàn)實世界的對象建模。典型的建模問題是學(xué)生選課問題。

一個課程可以有很多學(xué)生選,一個學(xué)生可以注冊很多課程。多對多的關(guān)系。

顯而易見地建一個Student類和一個Course類。每個類都包含一個對方的list。list表達了課程注冊關(guān)系。類似register和listCourses這樣的方法讓學(xué)生注冊課程或者列出他注冊的課程。

教授用這個問題來探討不同設(shè)計方案的折中問題。學(xué)生和課程的配置都不合理。一個聰明的數(shù)據(jù)建模者將能提煉出多對多關(guān)系模式。我們可以創(chuàng)建一個叫 ManyToMany<X, Y>的類來管理多對多關(guān)系。然后可以創(chuàng)建一個ManyToMany<CourseID, StudentID>對象來解決選課問題。

唯一的問題在于這樣做直接違背了教師課程中的意思。關(guān)系不是現(xiàn)實世界的對象,它最適合被表述為一種抽象概念。

而且它也可以用來解決泛化的抽象問題。ManyToMany類可以在任何合適的地方被復(fù)用。甚至可以讓ManyToMany作為一個有很多不同實現(xiàn)的接口。

我認(rèn)為我的教授是錯的。Java標(biāo)準(zhǔn)庫也包含了很多單純運算的類。為什么應(yīng)用程序員不可以也自己寫類似的類呢?更多內(nèi)容參考GOF設(shè)計模式。大部分模式都與抽象運算有關(guān),而不是現(xiàn)實世界的對象。比如職責(zé)鏈模式,在維基百科中被描述為“通過給予多個對象處理請求的機會,而避免調(diào)用請求與請求處理者耦合”。

解決方案:尋找代碼中的重復(fù)模式,構(gòu)建類來表示這些模式。使用這些類而不是在代碼中一再重復(fù)。

原文鏈接:http://my.oschina.net/feichexia/blog/112655

英文原文:http://www.lispcast.com/java-learn-from-clojure

責(zé)任編輯:張偉 來源: oschina
相關(guān)推薦

2012-05-22 21:56:49

Android

2012-06-13 01:23:30

開發(fā)者程序員

2024-08-22 13:40:08

開發(fā)者GPT-4oepoch

2015-02-04 10:55:14

2010-07-29 10:16:17

Linux內(nèi)核Linux內(nèi)存

2011-03-15 14:26:28

Java

2020-11-22 07:30:04

開發(fā)者技能工具

2015-04-01 09:54:47

Apple WatchAPP

2012-10-31 16:12:11

2012-01-04 09:18:32

iPhone開發(fā)者聯(lián)盟iDP中國開發(fā)者

2019-07-04 09:00:00

Web控制器架構(gòu)

2011-10-27 23:29:54

谷歌開發(fā)者日Google

2015-05-18 11:22:22

開發(fā)者Docker應(yīng)用LXC

2013-09-03 09:54:15

Web開發(fā)

2013-04-17 11:18:11

編程語言

2025-04-28 08:18:25

代碼遺漏空值強耦合

2022-01-21 08:01:59

System De前端開發(fā)

2013-03-11 11:20:05

2017-03-13 13:02:43

ARVRAndroid
點贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 日韩精品影院 | 91夜色在线观看 | 网站黄色在线 | 成人影院在线观看 | 国产精品a久久久久 | 99精品免费| wwwww在线观看 | 91免费观看| 91av久久久 | 精品国产乱码久久久 | 国产成都精品91一区二区三 | 一区二区精品在线 | 美女视频黄色的 | 国产精品一区二区在线观看 | 午夜电影合集 | 一区二区三区免费看 | 人人九九 | 久久免费资源 | hitomi一区二区三区精品 | 国产免费一区二区 | 免费观看一级毛片视频 | 国产精品久久久久久吹潮 | 欧美1区2区 | 日一日操一操 | 久久久久国产精品一区 | 免费在线看黄视频 | 欧美一区二区三区四区视频 | 中文字幕 欧美 日韩 | 久久精品欧美一区二区三区不卡 | 欧美性成人| 欧美成年黄网站色视频 | 365夜爽爽欧美性午夜免费视频 | 天天射美女 | 毛片区 | 韩日一区二区三区 | 亚洲一区二区久久 | 中文字幕不卡在线观看 | 一区精品视频在线观看 | 欧美日韩在线免费 | 欧美午夜精品久久久久久浪潮 | 欧美日韩电影一区 |