設計模式簡介
設計模式是一套被反覆使用、多數人知曉的、通過分類的、代碼設計經驗的總結。 使用設計模式是爲了可重用代碼、讓代碼更容易被他人理解、保證代碼可靠性。java
設計模式四大要素算法
模式名稱 編程
以一個恰當的詞來描述模式的問題、解決方案和效果。設計模式
問題 ide
描述應該在什麼時候使用設計模式。工具
解決方案this
提供設計問題的抽象描述和怎樣用一個具備通常意義的元素組合(類或對象)來解決這個問題。spa
效果 設計
描述設計模式應用的效果及使用設計模式應該權衡的問題。代理
設計模式六大原則
開閉原則
面向對象設計/編程 終極目標(實現開閉原則)
一個是對於拓展是開放的,另外一個是對於修改是關閉的
儘可能不要修改已有代碼
單一職責
不要讓一個類承擔過多的職責
里氏替換
繼承父類後,儘可能不要重寫父類的方法。
依賴倒轉
經過抽象或者接口來實現類與類之間的依賴關係。
接口隔離
創建單一接口,不要創建龐大/臃腫的接口
迪米特法則
一個實體儘量少的與另外一個實體發生接觸(依賴),
只須要知道入口和結果,沒必要在乎過程的實現。避免代碼過於耦合
設計模式分類:
建立型:主要處理對象的建立,實例化對象
結構型:處理類或對象的組合
行爲型:描述類或對象怎樣進行交互、職責分配
建立型模式之【單例模式】
問題
對於某些場景,確保一個類只有一個實例對象是很重要的,而且這個實例是易於被訪問的。
解決方案
將實例化操做隱藏在一個類中,由這個類來保證明例的建立和惟一性。
/** * @redame 單例模式 餓漢 */ public class SingletonObjectA { private static SingletonObjectA instance = new SingletonObjectA(); private SingletonObjectA(){} public static SingletonObjectA getInstance(){ return instance; } }
/** * @redame 單例模式 懶漢 */ public class SingletonObjectB { private static volatile SingletonObjectB instance = null; private SingletonObjectB(){} public static SingletonObjectB getInstance(){ if(instance==null){ synchronized(instance){ if(instance == null){ instance = new SingletonObjectB(); } } } return instance; } }
建立型模式之【工廠模式】
問題
當一個類沒法肯定要建立哪一種類的對象,或者須要經過子類來肯定具體對象的建立時。
解決方案
建立一個建立對象的工廠,工廠在程序執行過程當中具體決定建立哪一個對象。
/** * @redame 普通工廠模式 */ public class MessageFactoryA { public static String MAIL="MAIL"; public static String SMS="SMS"; public static String WE_CHAT="WE_CHAT"; public Sender product(String type){ if(MessageFactoryA.MAIL.equals(type)){ return new MailSender(); } else if(MessageFactoryA.SMS.equals(type)){ return new SmsSender(); } else if(MessageFactoryA.WE_CHAT.equals(type)){ return new WechatSender(); } return null; } }
/** * @redame 工廠方法模式 */ public class MessageFactoryB { public Sender productMail(){ return new MailSender(); } public Sender productSMS(){ return new SmsSender(); } public Sender productWechat(){ return new WechatSender(); } }
結構型模式之【適配器模式】
問題
有時,爲複用而設計的工具箱類不可以被複用的緣由,僅僅是由於它的接口與專業應用領域所須要的接口不匹配。
解決方案
應用經過適配器調用接口,由適配器使得工具箱類能夠被使用。
public class Source { public void method1(){ System.out.println("一個普通方法實現."); } }
public interface Targetable { //與原類中的方法相同 public void method1(); //新類中的方法 public void method2(); }
/** * 類適配器 */ public class SpecialAdapter extends Source implements Targetable { @Override public void method2() { System.out.println("這是一個特殊方法實現."); } }
/** * 對象適配器 */ public class SpecialAdapter implements Targetable { /** * 可匹配Source的子類 **/ private Source source; public SpecialAdapter(Source source){ super(); this.source = source; } @Override public void method1() { source.method1(); } @Override public void method2() { System.out.println("這是一個特殊方法實現."); } }
public static void main(String[] args) { //類適配 Targetable target = new SpecialAdapter(); target.method1(); target.method2(); //對象適配 Targetable adapter = new SpecialAdapter(new Source()); adapter.method1(); adapter.method2(); }
結構型模式之【代理模式】
問題
對象的訪問須要被控制,不容許其餘對象任意訪問此對象接口。
解決方案
代理類開放接口提供訪問,全部訪問由代理類決定具體的調用。
/** *抽象類 */ public abstract class AbstractObject { //代理方法 public abstract void operation(); }
/** * 代理對象 */ public class RealObject extends AbstractObject { @Override public void operation() { System.out.println("具體執行任務."); } }
/** * 代理類 */ public class ProxyObject extends AbstractObject { //代理對象 RealObject realObject = new RealObject(); @Override public void operation() { System.out.println("執行任務前, 作一些什麼事情."); realObject.operation(); } }
public static void main(String[] args) { AbstractObject obj = new ProxyObject(); obj.operation(); }
行爲模式之【觀察者模式】
問題
將一個系統分割成一系列相互協做的類有一個常見的反作用:須要維護相關對象間的一致性,然而維護對象間的一致性可能致使各種之間的緊密耦合,這樣將下降它們的可重用性。
解決方案
觀察者模式創建一個目標和任意個依賴它的觀察者,一旦目標狀態發生改變,全部的觀察者都獲得通知。
public abstract class AbstractSubject implements Subject { private Vector<Observer> observerList = new Vector<Observer>(); public void add(Observer observer) { observerList.add(observer); } public void del(Observer observer) { observerList.remove(observer); } public void notifyObservers() { for (Observer observer : observerList) { observer.update(); } } }
public class MySubject extends AbstractSubject { @Override public void operation() { System.out.println("執行方法, 狀態修改. "); notifyObservers(); } }
public interface Observer { public void update(); }
public class ObserverA implements Observer { @Override public void update() { System.out.println("觀察者A觀察到對象的變化."); } }
public class ObserverB implements Observer { @Override public void update() { System.out.println("觀察者B觀察到對象的變化."); } }
public static void main(String[] args) { AbstractSubject subject = new MySubject(); subject.add(new ObserverA()); subject.add(new ObserverB()); subject.operation(); } =======================運行結果 執行方法, 狀態修改. 觀察者A觀察到對象的變化. 觀察者B觀察到對象的變化.
行爲模式之【策略模式】
問題
開發中常見的狀況:實現某功能能夠有多種算法或者策略,可根據實際狀況選擇不一樣的算法或策略來完成該功能。若是將全部算法或策略都封裝在一個類中,提供不一樣方法來實現,這個類就變得臃腫,並且新增算法或策略時,須要修改封裝算法類的源碼。
解決方案
使用不一樣類來封裝不一樣的算法
public interface MemberStrategy { /** * 計算圖書的價格 * @param booksPrice 圖書的原價 * @return 計算出打折後的價格 */ public double calcPrice(double booksPrice); }
public class AdvancedMemberStrategy implements MemberStrategy { @Override public double calcPrice(double booksPrice) { System.out.println("高級會員8折"); return booksPrice * 0.8; } }
public class IntermediateMemberStrategy implements MemberStrategy { @Override public double calcPrice(double booksPrice) { System.out.println("中級會員9折"); return booksPrice * 0.9; } }
public class PrimaryMemberStrategy implements MemberStrategy { @Override public double calcPrice(double booksPrice) { System.out.println("初級會員沒有折扣"); return booksPrice; } }
public class Price { //持有一個具體的策略對象 private MemberStrategy strategy; /** * @param strategy */ public Price(MemberStrategy strategy) { super(); this.strategy = strategy; } /** * 計算圖書的價格 * @param booksPrice 圖書的原價 * @return 計算出打折後的價格 */ public double quote(double booksPrice){ return this.strategy.calcPrice(booksPrice); } }
public static void main(String[] args) { //選擇並建立須要使用的策略對象 MemberStrategy strategy = new AdvancedMemberStrategy(); //建立環境 Price price = new Price(strategy); //計算價格 double quote = price.quote(300); System.out.println("圖書的最終價格爲:" + quote); } =========運行結果 高級會員8折 圖書的最終價格爲:240.0