Java筆記 設計原則與框架思想
前言
即使類的設計很糟糕,也還是有可能實現一個應用程序,使之運行并完成所需的工作。一個已完成的應用程序能夠運行,但并不能表明程序內部的結構是否良好。 當維護程序員想要對一個已有的軟件做修改的時候,問題才會浮現出來。比如,程序員試 圖糾正已有軟件的缺陷,或者為其增加一些新的功能。顯然,如果類的設計良好,這個任務就 可能很輕松;而如果類的設計很差,那就會變得很困難,要牽扯大量的工作。 在大的應用軟件中,這樣的情形在最初的實現中就會發生了。如果以不好的結構來實現軟 件,那么后面的工作可能變得很復雜,整個程序可能根本無法完成,或者充滿缺陷,或者花費 比實際需要多得多的時間才能完成。在現實中,一個公司通常要維護、擴展和銷售一個軟件很 多年,很可能今天在商店買到的軟件,其最初的版本是在十多年前就開始了的。在這種情形下, 任何軟件公司都不能忍受不良結構的代碼。 既然很多不良設計的效果會在試圖調整或擴展軟件時明顯地展現出來,那么就應該以調整 或擴展軟件來鑒別和發現這樣的不良設計。
知識點:
面向對象程序設計的一些基本原則:
-
除代碼復制 :
相同的代碼抽取封裝成一個函數
消除代碼復制的兩個基本手段,就是函數和父類。
-
1.封裝: 降低耦合
正宗OOP的方案:“讓雙方都不了解雙方,只知道你能干嘛,你能給我什么,你給我就好,我懶得自己拿”
(當修改一個類時,另一個類不需要聯動修改,別讓一個類大量使用另一個類的成員變量,別讓兩個類都有大量的代碼和某個類的成員變量相關)- 程序設計的目標是一系列通 過定義明確的接口通信來協同工作的類。
- 耦合度反映了這些類聯系的緊密度。
- 我們努力要獲得 低的耦合度,或者叫作[松耦合(loose coupling)]。
- 耦合度決定修改應用程序的容易程度。
- 在一個松耦合的系統中,常常可以修改一個類,但同時不會修改其他類,而且 整個程序還可以正常運作。
- 聚合與程序中一個單獨的單元所承擔的任務的數量和種類相對應有關,它是針對類或方法 這樣大小的程序單元而言的理想情況下,一個代碼單元應該負責一個聚合的任務(也就是說,一個任務可以被看作是 一個邏輯單元)。
- 一個方法應該實現一個邏輯操作,而一個類應該代表一定類型的實體。
- 聚合 理論背后的要點是重用:如果一個方法或類是只負責一件定義明確的事情,那么就很有可能在 另外不同的上下文環境中使用。
自己的成員不要讓別人來操作,對方需要什么,自己學會一個方法給他,別讓別人懂那么多東西
封裝----把流浪在外地的代碼帶回家管理:降低耦合的一個體現就素其他類不會直接用到我的成員變量,他需要利用我的成員變量干嘛,我就干嘛,不讓外人來搗鼓我的東西,最后把結果告訴外人就行。
-
2.可擴展性:
可擴展性的意思就是代碼的某些部分不需要經過修改就能適應將來可能的變化。
- 當添加一個可以歸為同一類的類型時,如在一群子類中再添加一個平行子類,保證其他原有的使用到這些子類對象的代碼不需要變動--->"以不變,應將來的萬變"
- 優秀的軟件設計者的一個素質就是有預見性。什么是可能會改變的?什么是可以假設在軟 件的生命期內不會改變的? 在游戲的很多類中硬編碼進去的一個假設是,這個游戲會是一個基于字符界面的游戲,通 過終端進行輸入輸出,會永遠是這樣子嗎? 以后如果給這個游戲加上圖形用戶界面,加上菜單、按鈕和圖像,也是很有意思的一種擴展
-
聚合: -- 開放接口
- 自己能實現的自己說了算自己實現,然后告訴對方結果。
- 例如房間的門打開的方法,房間自己幫別人打開就行,置于我用手打開還是腳打開都自己話事,你不用管,反正門是給你打開了,不用你動手。
用接口實現聚合----給類實現新的方法,把具體細節徹底隱藏在該類中,只暴露結果的函數接口供外界使用,而如何實現該方法從此于外界無關。 - 以后若改動優化接口里面的實現邏輯代碼,外部調用該接口的代碼無需改動
-
靈活性:-- 硬編碼,我們不約哦
用容器實現靈活性----替換掉"硬編碼" === HashMap<Key,Value>的加入,可以將原本硬編碼在類內部想同Value類型的成員變量通過Key-Value的方式替換,實現靈活加入Value對象的設計。
例如一個房子類House原本有一個房間Room no_a:需要一個房間類的成員變量,房號為變量名:Room no_a;當我們要為這個房子新建一個新房間時,則需要修改House類,添加一個新的成員變量Room no_b。當后續房子內又要添加新的房間時,則又需要修改House類。此時,House類的可擴展性就不高。當我們使用HaspMap<String,Room>來代替掉上述的Room成員變量,則外部需要給House添加新房子時,只需要把key當做原本的房間名,value作為新房間的對象,傳入給House類的HashMap當中,就可以給House添加新房間了,而不需要改動House類,通過容器來實現是不是很靈活呢! - 維持接口:內部實現方式可以根據需要改變,而外部使用到該接口的程序可以不知道發生了什么。----層次設計理念 </ul> </li>
-
3.框架+數據:提高可擴展性
從程序中識別出框架和數據,以代碼實現框架,將部分功能以數據的方式加載,這樣能在很大程度上實現可擴展性。
- 目標:把程序的
硬編碼
解成框架+數據
的結構。而原本硬編碼的東西一般為成員變量、函數
。 - 框架:原本硬編碼的東西,通過容器,做成一個框架----HashMap對應關系、接口函數。
- 數據:放在HaspMap(容器)中的鍵值對(內容)
-
成員變量 改成數據
//原成員變量 private Room room_a; private Room room_b; //改造: String類型的Key則表示room_a變量名,Room類型的Value則表示room_a 的引用對象 private HashMap<String,Room> rooms = new HashMap<String,Room>(); rooms.put("room_a",new Room()); //當需要用到room_a的時候,就 rooms.get("room_a")
- 函數(處理邏輯)改成數據
思路solution:上述將成員變量通過鍵值對的方式做成HashMap的item,是框架的基本思想。那么,參照這個基本思想,我們需要一個存放函數的HashMap,而Key、Value都是對象,方法卻不是對象,怎么存進去呢?
登登登登---將方法封裝到一個類里面,不就可以實例化一個對象放到HashMap里面了嗎,然后通過類來調用辣個方法即可。因為HashMap通過泛型約束存放的對象,所依先構建一個父類,代表方法對象,例如叫Handler。不同的方法則設計為Handler的子類,則所有方法類都可以存進這個HashMap<String,Handler>里面,讓這一個HashMap管理了:pass
</ul> </li>
</ul>
- 設計類的時候,類的成員首要思考為private,萬不得已才public
- 要評判某些設計比其他的設計優秀,就得定義一些在類的設計中重要的術語,以用來討論 設計的優劣。對于類的設計來說,有兩個核心術語:耦合和聚合。
耦合
這個詞指的是類和類之間的聯系- 注意String -- StringBuffer的選用,當需要將大量字符串組合為一個字符串時,采用StringBuffer。若僅僅接收一個String對象,則使用String即可。
- 什么時候要設計傳入this作為參數的方法?
當該方法不在this所指的那個類里面,又要用到那個類的成員,則需要設計出入this。而實際方法體的參數類型則為this所指的類型。而且這跟“動態”關系很大,而不是單純的需要那個類的實例對象來進行操作,而是需要運行狀態下的那個對象。因為同一個類的不同對象,成員變量是不一樣的。(講得又點繞,改天調整)
應用:
第一步:消除代碼復制
以一個類為單元,找到該類中重復或相似的代碼段,封裝成函數
第二步:封裝 降低耦合--降低兩個之間的聯系
1、找其他類中是否直接用到了該類的成員變量,把這部分邏輯封裝成成員函數,并把成員變量設為private,開放一個接口把結果返回給調用類。注意,給別人最需要的最小部分,如原本代碼是System.out.println(balabalabala),那么只需要把這個balabala結果返回去即可,不要幫對方完成println等操作,
重點:給數據
2、通過getter、setter給私有成員開放接口供外部使用。但這不是真正OOP的解決方案,這是無可奈何的過渡方案,這樣是直接掏了心肝肺...)第三步:聚合 -- 開放接口
(其實第二步封裝已經做過聚合了)
自己能實現的己說了算自己實現,然后告訴對方結果。
例如房間的門打開的方法,自己幫別人打開就行,置于我用手打開還是腳打開都自己話事,你不用管,反正門是給你打開了,不用你動手。第四步:框架 + 數據 --- 可擴展性
1、成員變量:找到類里面的成員變量,思考某類型的成員變量日后是否有增加的可能,例如House里面有一個房間Room,日后可能因為裝修,多出幾個房間,則把這類Room的成員變量改成用HashMap容器來存放
2、方法函數:將方法封裝到一個方法類及其子類中,每個子類表示一個方法的實現。父類設計一個相同的接口,子類去實現不同的方法體。在調用方法的地方,用父類的變量調用父類設計的接口方法,虛擬機便會根據程序實際運行狀態,調用對應子類里面的方法實現。切記框架設計不要有例外,添加任何新的東西,都不要用硬編碼來判斷。
拾遺:
注意,代碼中的漢字用的是UTF-8編碼。請在Eclipse里將文件的編碼格式改為UTF-8:
File --> Properties --> Resource (Text file encoding) ==> Other [UTF-8]Eclipse導入工程亂碼問題
來自:http://www.jianshu.com/p/8e2a7cc4dd79