面向對象六大原則
1.單一職責原則
? ? 所謂職責是指類變化的原因诀黍。如果一個類有多于一個的動機被改變,那么這個類就是具有多于一個的職責。單一職責原則是指一個類或者模塊應該有且只有一個改變他的原因鼠冕。通俗的說就是一個類只負責一項職責。
2.開閉原則
? ? 對于擴展是開放的胯盯,這意味著模塊的行為是可以擴展的懈费。當應用的需求改變時,我們可以對模塊進行擴展博脑,而對于其修改是關閉的憎乙,不要改動模塊的源代碼。通俗的說就是盡量通過拓展的方式實現(xiàn)系統(tǒng)的升級維護和新功能的添加趋厉,而不是修改已有的源代碼寨闹。
3.里氏替換原則
????使用抽象和多態(tài)將設計中的靜態(tài)結構改為動態(tài)結構,維持設計的封閉性君账。任何基類可以出現(xiàn)的地方,子類一定可以出現(xiàn)沈善。
? ? 在軟件中乡数,將一個基類對象替換成他的子類對象,程序將不會產生任何錯誤和異常闻牡。反過來則不成立净赴。在程序中盡量使用基類類型來對對象進行定義,而在運行時再確定其子類類型罩润,用子類對象來替換父類對象玖翅。
4.依賴倒置原則????
? ? 高層次的模塊不應該依賴于低層次的模塊,他們都應該依賴于抽象割以。抽象不應該依賴于具體實現(xiàn)金度,具體實現(xiàn)應該依賴于抽象。程序要依賴于抽象接口严沥,不要依賴于具體實現(xiàn)猜极。簡單來說就是要求對抽象進行編程,不要對實現(xiàn)進行編程消玄。這樣就降低了客戶與實現(xiàn)模塊間的耦合跟伏。(各個模塊之間相互傳遞的參數(shù)聲明為抽象類型丢胚,而不是聲明為具體的實現(xiàn)類)
5.接口隔離原則
? ? 一個類對另一個類的依賴應該建立在最小的接口上。其原則是將非常龐大受扳,臃腫的接口拆分成更小更具體的接口携龟。
6.迪米特原則
????又叫做最少知識原則,一個對象對其他對象應該有盡可能少的了解勘高。通俗的講骨宠,一個類應該對自己需要耦合或者調用的類知道的最少,不關心被耦合或調用類的內部的實現(xiàn)相满,只負責調用你提供的方法层亿。
設計模式
1.單例設計模式
作用:保證在java應用程序中,一個類class只有一個實例存在立美。
好處:由于單例模式在內存中只有一個實例匿又,減少了內存的開銷。優(yōu)化和共享資源訪問建蹄。
單例模式可以避免對資源的多重占用碌更,例如寫一個文件時,由于只有一個實例存在于內存中洞慎,避免對同一個資源文件的同時寫操作痛单。
使用情況:建立目錄,數(shù)據(jù)庫操作等單線程操作劲腿。某個需要被頻繁訪問的實例對象旭绒。
基本的實現(xiàn)思路
單例模式要求類能夠有返回對象一個引用(永遠是同一個)和一個獲得該實例的方法(必須是靜態(tài)方法,通常使用getInstance這個名稱)焦人。
單例的實現(xiàn)主要是通過以下兩個步驟:
將該類的構造方法定義為私有方法挥吵,這樣其他處的代碼就無法通過調用該類的構造方法來實例化該類的對象,只有通過該類提供的靜態(tài)方法來得到該類的唯一實例花椭;
在該類內提供一個靜態(tài)方法忽匈,當我們調用這個方法時,如果類持有的引用不為空就返回這個引用矿辽,如果類保持的引用為空就創(chuàng)建該類的實例并將實例的引用賦予該類保持的引用丹允。
使用方法:
1.餓漢式
public class Single{
? ? private static Single mInstance = new Single();
? ? private Single(){}
? ? public static Single getInstance(){
? ? ????return mInstance;
????}
}
優(yōu)點:這種寫法比較簡單,就是在類裝載的時候就完成實例化袋倔。避免了線程同步問題雕蔽。
缺點:在類裝載的時候就完成實例化,沒有達到Lazy Loading的效果奕污。如果從始至終從未使用過這個實例萎羔,則會造成內存的浪費。
2.餓漢式靜態(tài)代碼塊
public class Single{
? ? private static Single mInstance ;
? ? static{mInstance=new Single();}
????private Single(){}
? ? public Single getInstance(){
? ? ? ? ? ?return mInstance;
}
這種方式和上面的方式其實類似碳默,只不過將類實例化的過程放在了靜態(tài)代碼塊中贾陷,也是在類裝載的時候缘眶,就執(zhí)行靜態(tài)代碼塊中的代碼,初始化類的實例髓废。優(yōu)缺點和上面是一樣的巷懈。
3.懶漢式 ?線程不安全(不可用):
public class Single{
? ? private static Single mInstance;
????private Single(){}
? ? public static Single getInstance(){
? ? ? ? if(mInstance == null){
? ? ? ? ? ? ? ? ? ?mInstance = new Single();
????????????????????????}
? ????? return mInstance;
????}
}
這種寫法起到了Lazy Loading的效果慌洪,但是只能在單線程下使用顶燕。如果在多線程下,一個線程進入了if (singleton == null)判斷語句塊冈爹,還未來得及往下執(zhí)行涌攻,另一個線程也通過了這個判斷語句,這時便會產生多個實例频伤。所以在多線程環(huán)境下不可使用這種方式恳谎。
4.懶漢式:(線程安全,同步方法)[不推薦用]
public class Single{
? ? private static Single mInstance;
????private Single(){}
? ? public static synchronized ?Single getInstance(){
? ? ? ? if(mInstance == null){
? ? ? ? ? ? ? ? ? ? mInstance = new Single();
????????????????}
? ????? return mInstance;
????}
}
解決上面第三種實現(xiàn)方式的線程不安全問題憋肖,做個線程同步就可以了因痛,于是就對getInstance()方法進行了線程同步。
缺點:效率太低了岸更,每個線程在想獲得類的實例時候鸵膏,執(zhí)行getInstance()方法都要進行同步。而其實這個方法只執(zhí)行一次實例化代碼就夠了怎炊,后面的想獲得該類實例谭企,直接return就行了。方法進行同步效率太低要改進结胀。
5.懶漢式:(線程安全赞咙,同步代碼塊)[不可用]
public class Single{
? ? private static Single mInstance = null;
????private Single(){}
? ? public static Single getInstance(){
? ? ? ? if(mInstance == null){
? ? ? ? ? ? synchronized(Single.class){
? ? ? ? ? ? ? ? ? ? mInstance = new Single();
????????????}
????????}
? ????? return mInstance;
????}
}
由于第四種實現(xiàn)方式同步效率太低,所以摒棄同步方法糟港,改為同步產生實例化的的代碼塊。但是這種同步并不能起到線程同步的作用院仿。跟第3種實現(xiàn)方式遇到的情形一致秸抚,假如一個線程進入了if (singleton == null)判斷語句塊,還未來得及往下執(zhí)行歹垫,另一個線程也通過了這個判斷語句剥汤,這時便會產生多個實例。
6.懶漢式:雙重檢查[推薦用]
public class Single{
? ? private static Single mInstance = null;
????private Single(){}
? ? public static Single getInstance(){
? ? ? ? if(mInstance == null){
? ? ? ? ? ? synchronized(Single.class){
? ? ? ? ? ? ? ? if(mInstance ==null){
? ? ? ? ? ? ? ? ? ? mInstance = new Single();
????????????????}
????????????}
????????}
? ????? return mInstance;
????}
}
Double-Check概念對于多線程開發(fā)者來說不會陌生排惨,如代碼中所示吭敢,我們進行了兩次if (singleton == null)檢查,這樣就可以保證線程安全了暮芭。這樣鹿驼,實例化代碼只用執(zhí)行一次欲低,后面再次訪問時,判斷if (singleton == null)畜晰,直接return實例化對象砾莱。
優(yōu)點:線程安全;延遲加載凄鼻;效率較高腊瑟。
7.靜態(tài)內部類[推薦用]
public class Single{
????private Single(){}
? ? private static class SingleInstance{
? ? ? ? private static final Single MINSTANCE = new Single();
????}
? ? public static Single getInstance(){
? ? ? ? return SingleInstance.MINSTANCE;
????}
}
這種方式跟餓漢式方式采用的機制類似,但又有不同块蚌。兩者都是采用了類裝載的機制來保證初始化實例時只有一個線程闰非。不同的地方在餓漢式方式是只要Singleton類被裝載就會實例化,沒有Lazy-Loading的作用峭范,而靜態(tài)內部類方式在Singleton類被裝載時并不會立即實例化财松,而是在需要實例化時,調用getInstance方法虎敦,才會裝載SingletonInstance類游岳,從而完成Singleton的實例化。
類的靜態(tài)屬性只會在第一次加載類的時候初始化其徙,所以在這里胚迫,JVM幫助我們保證了線程的安全性,在類進行初始化時唾那,別的線程是無法進入的访锻。
優(yōu)點:避免了線程不安全,延遲加載闹获,效率高期犬。
8.枚舉[推薦用]
public enum Single{
? ? ? ? INSTANCE;
? ? ? ? public void getInstance(){
? ? ????}
}
借助JDK1.5中添加的枚舉來實現(xiàn)單例模式。不僅能避免多線程同步問題避诽,而且還能防止反序列化重新創(chuàng)建新的對象龟虎。可能是因為枚舉在JDK1.5中才添加沙庐,所以在實際項目開發(fā)中鲤妥,很少見人這么寫過。
2.工廠模式
定義:定義一個用戶創(chuàng)建對象的接口拱雏,讓子類決定實例化哪個對象棉安。工廠方法使一個類的實例化延遲到其子類。對同一個接口的實現(xiàn)類進行管理和實例化創(chuàng)建铸抑。
ex:
抽象產品類:
public abstract class Product{
? ? public abstract void method();//產品的抽象類方法贡耽,由具體的產品類去實現(xiàn)。
}
具體產品類A
public class ProductA extend Product{
? ? @override
? ? public void method(){
? ? ? ? Log.d("zrl","我是產品A")
????}
}
具體產品類B
public class ProductB extends Product{
? ? @override
? ? public void method(){
? ? ? ? Log.d("zrl","我是產品B")
????}
}
抽象工廠類:
public abstract class Factory{
? ? public abstract Product createProduct();
}
具體工廠類:
public class FactoryA extends Factory{
? ? @override
? ? public Procuct createProduct(){
? ? ? ? return new ProductA();
? ? ? ? //return new ProductB(); ??
????}
}
客戶類:
public class Client{
? ? public static void main(String[] args){
????????Factory factoryA =new FactoryA();
????????Factory factoryB =new FactoryB();
????????Product productA= factoryA.createProduct();
????????Product productB = factoryB.createProduct();
????????productA.method();
????????productB.method();
????????FactoryA factoryA1 =new FactoryA();
????????Product product = factoryA1.createProduct();
????????product.method();
????}
}
打印結果:我是產品A?
? ? ? ? ? ? ? ? ?我是產品B?
? ? ? ? ? ? ? ? ?我是產品A
反射的方式也可以表現(xiàn)工廠設計模式:
抽象工廠類:
public abstract class Factory{
? ? public abstract <T extends Product> T createProduct(Class<T> cls);
}
具體工廠類:(通過反射獲取)
public class FactoryA extends Factory{
? ? @override
? ? public <T extends Product> T createProduct(Class<T> cls){
? ? ? ? Product p = null;
? ? ? ? try{
? ? ? ? ? ? p = (Product)Class.forName(cls.getName).newInstance();
????????}catch(Exception e){
? ? ? ? ? ? ? ? ...
????????}
? ? ? ? return (T) p ;
????}
}
client的實現(xiàn)
Factory factory = new FactoryA();
Product b = factory.createProduct(ProductB.class);
b.method();
3.適配器模式
我們經常碰到要將兩個沒有關系的類組合在一起使用蒲赂,第一解決方案是:修改各自類的接口阱冶,但是如果我們沒有源代碼,或者凳宙,我們不愿意為了一個應用而修改各自的接口熙揍。 怎么辦?
使用Adapter,在這兩種接口之間創(chuàng)建一個混合接口氏涩。
定義:把一個類的接口變成客戶端所期待的另一種接口届囚,從而使原本因接口不匹配而無法再一起工作的兩個類能夠在一起工作。
使用場景:
1)系統(tǒng)需要使用現(xiàn)有的類是尖,而此類的接口不符合系統(tǒng)的需要意系,即接口不兼容。
2)想要建立一個可以重復的類饺汹,用于與一些彼此之間沒有太大關聯(lián)的一些類蛔添,包括一些可能在將來引進的類一起工作
3)需要一個統(tǒng)一的輸出接口,而輸入端的類型不可預知兜辞。
模式中的角色:
需要適配的類(Adaptee):需要適配的類迎瞧。
適配器(Adapter):通過包裝一個需要適配的對象,把原接口轉換成目標接口逸吵。
目標接口(Target):客戶所期待的接口凶硅。可以是具體的或抽象的類扫皱,也可以是接口足绅。
public interface Target{
? ? void targetMethod();
}
public class Adaptee {
? ? public void getRequest(){
? ? ? ? Log.d("zrl",“適配類的方法”);
????}
}
實現(xiàn):
public class Adapter implements Target{
? ? Adaptee adaptee;
? ? public Adapter(Adaptee ad){
? ? ? ? adaptee = ad;
????}
? ? public void targetMethod(){
? ? ? ? adaptee.getRequest();
????}
}
測試類:
public class Client{
? ??????public static void main(String[] args) {
????????// 需要先創(chuàng)建一個被適配類的對象作為參數(shù)
????????Target target=new Adapter(new Adaptee());
????????target.targetMethod();
????}
}
如果Target和 Adaptee都是接口橱赠,并且都有實現(xiàn)類壳贪。 可以通過Adapter實現(xiàn)兩個接口來完成適配。?
優(yōu)點:
系統(tǒng)需要使用現(xiàn)有的類嚷掠,而此類的接口不符合系統(tǒng)的需要段多。那么通過適配器模式就可以讓這些功能得到更好的復用首量。 將目標類和適配者類解耦,通過引入一個適配器類重用現(xiàn)有的適配者類进苍,而無需修改原有代碼蕾总,更好的擴展性。
缺點:
過多的使用適配器琅捏,會讓系統(tǒng)非常零亂,不易整體進行把握递雀。比如柄延,明明看到調用的是A接口,其實內部被適配成了B接口的實現(xiàn)。如果不是必要搜吧,不要使用適配器市俊,而是直接對系統(tǒng)進行重構。
4.責任鏈模式
? ? 使多個對象都有機會處理請求滤奈,從而避免請求的接受者和發(fā)送者之間的耦合關系摆昧,將這些對象連接成一條鏈,并沿著這條鏈傳遞該請求蜒程,直到有一個對象處理他為止绅你。發(fā)送這個請求的客戶端并不知道鏈上哪個對象最終處理這個請求,這使得系統(tǒng)可以在不影響客戶端的情況下動態(tài)的重新組織和分配責任昭躺。
編程中小提現(xiàn):
if(a<10){
? ? ...
}
else if (a<20){
? ? ...
}
else if(a<30){
? ? ...
}
else{
? ? ...
}
優(yōu)點:可以降低系統(tǒng)的耦合度(請求者與處理者代碼分離)忌锯,簡化對象的相互連接,同時增強給對象指派責任的靈活性领炫,增加新的請求處理類也很方便偶垮。
缺點:不能保證請求一定被接收,且對于比較長的責任鏈帝洪,請求的處理可能涉及到多個處理對象似舵,系統(tǒng)性能將受到一定影響,而且在進行代碼調試時不方便葱峡,每次都是從鏈頭開始砚哗。
5.觀察者模式
定義:定義對象間一種一對多的依賴關系,使得每當一個對象改變狀態(tài)族沃,則所依賴于它的對象都會得到通知并被自動更新频祝。