1、 基本概述ide
1:現實中存在三角插頭適配成雙插頭,等其餘各類形式的適配器來鏈接不兼容的兩個物體。同理在代碼中也存在適配器模式來兼容兩個不一樣的代碼接口。性能
2:KTV包間打開一個啓動開關,就打開party模式(音響、屏幕、燈光、換氣、點歌臺等),一個簡單的開關來控制其餘更多的任務。同理在代碼中也存在外觀模式來簡化子系統(更多任務)的功能。測試
2、詳細說明this
1.適配器模式:將一個類的接口、轉換成客戶指望的另外一個接口,適配器讓本來接口不兼容的類能夠合做無間。編碼
這個適配器模式充滿良好的OO設計原則,使用對象組合,以修改的接口包裝被適配者,這種作法還有額外的優勢,那就是被適配者的任何子類,均可以搭配着適配器使用。spa
問:一個適配器須要作多少「適配」工做?若是我須要實現一個很大的目標接口,彷佛有「不少」工做要作。設計
答:實現一個適配器所須要進行的工做,的確和目標接口的大小成正比。若是不用適配器,你就必須改寫客戶端的代碼來調用這個新的接口,將會花許多力氣來作大量的調查工做和代碼改寫工做。相比之下,提供一個適配器類,將全部的改變封裝在一個類中,是比較好的作法。code
問:一個適配器只可以封裝一個類嗎?對象
答:適配器模式的工做是將一個接口轉換成另外一個。雖然大多數的適配器模式所採起的例子都是讓一個適配器包裝一個適配器者,但咱們都知道這個世界其實複雜多了,因此你可能絮叨一些情況,須要讓一個適配器包裝多個被被適配者。這涉及另外一個模式,被稱爲外觀模式,人們經常將外觀模式和適配器模式混爲一談。blog
問:萬一個人系統中新舊並存,舊的部分指望舊的廠商接口,但咱們卻已經使用新廠商的接口編寫了這一部分。
答:能夠建立一個雙向的適配器,支持兩邊的接口。想建立一個雙向的適配器,就必須實現所涉及的兩個接口,這樣這個適配器能夠當作舊的接口、新的接口使用。
其實適配器模式有兩種形式,對象適配器(在上面進行了說明)、和類適配器,類適配器須要用到多重繼承(在C#中是不可能的)。
2.外觀模式:提供了一個統一的接口,用來訪問子系統中的一羣接口,外觀定義了一個高層接口,讓子系統更容易使用。
下圖爲外觀模式的示意圖
假若有一個家庭影院,在咱們觀賞電影時,必須先執行一些任務(普通方式)。
(1) 打開爆米花機
(2) 開始爆米花機
(3) 將燈光調暗
(4) 放下屏幕
(5) 打開投影機
(6) ...
(7) 省略更多步驟
(8) 開始播放
面對以上中狀況,可使用外觀來簡化接口。以下圖
問:若是外觀封裝了子系統的類,那麼須要底層功能的客戶如何接觸這些了類?
答:外觀沒有「封裝」子系統的類,外觀只提供簡化的接口。因此客戶若是以爲有必要,依然能夠直接使用子系統的類。這是外觀模式一個很好的特徵,提供簡化的接口的同時,依然將系統完整的功能暴露出來,以供須要的人使用。
問:每一個子系統只能有一個外觀嗎?
答:不,你能夠爲一個子系統建立許多個外觀。
問:可不能夠這樣說,適配器模式和外觀模式之間的差別在於,適配器包裝一個類,而外觀能夠表明許多類?
答:不對!適配器模式將一個或多個類接口變成客戶所指望的一個接口。雖然大多數教科書所採用的例子中適配器只適配一個類,可是你能夠適配許多類來提供一個接口讓客戶編碼。相似的,一個外觀也能夠只針對一個擁有複雜接口的類提供簡化的接口。兩種模式的差別,不在於它們「包裝」了幾個類,而是在於它們的意圖。(可在總結中查看)
3.設計原則:最少知識原則:只和你的密友談話。
最少知識原則告訴咱們要減小對象之間的交互,只留下幾個「密友」。這個原則但願咱們在設計中,不要讓太多的類耦合在一塊兒,省得修改系統中一部分,會影響到其餘部分。若是許多類之間相互依賴,那麼這個系統就會變成一個易碎的系統,它須要花許多成本維護,也會由於太複雜而不容易被其餘人瞭解。
如何不要贏得太多的朋友和影響太多的對象。
這個原則提供了一些方針:就職何對象而言,在該對象的方法內,咱們只應該調用屬於如下範圍的方法:
(1) 該對象自己;
(2) 被當作方法的參數而傳遞進來的對象;
(3) 此方法所建立或實例化的任何對象;
(4) 對象的任何組件(把組件想象成是被實例化的變量所引用的任何對象);
問:還有另外一個原則,叫作得墨忒耳法則(Law of Demeter),它和最少知識原則有什麼關係?
答:其實兩個名詞指的是同一個原則,咱們傾向於使用最少知識原則來稱呼它是由於如下兩個緣由。
(1) 這個名字更直接。
(2) 法則(Law)給人的感受是強制的。事實上,沒有任何原則是法律,全部的原則都應該在有幫助的時候才遵照。
全部的設計都難免須要折衷(在抽象和速度之間取捨,在空間和時間之間平衡...)。雖然原則提供了方針,但在採用以前,必須全盤考慮全部的因素。
問:採用最少知識原則有什麼缺點嗎?
答:雖然這個原則減小了對象之間的依賴,研究顯示這會減小軟件的維護成本;可是採用這個原則也會致使更多的「包裝」類被製造出來,以處理和其餘組件的溝通,這可能會致使複雜度和開發時間的增長,並下降運行時的性能。
4.總結:
對比三種模式的意圖:
裝飾者:不改變接口,但加入責任(將一個對象包裝起來以增長新的行爲和責任)。
適配器:將一個接口轉成另外一個接口(將一個對象包裝起來以改變其接口)。
外觀:讓接口更簡單(將一羣對象「包裝」起來以簡化其接口)。
3、代碼列表
//適配器模式相關測試類 public interface Iterator<T> { bool HasNext(); T Next(); void Remove(); } public class EnumerationIterator<T> : Iterator<T> { private IEnumerator<T> enumerator; public EnumerationIterator(IEnumerable<T> enumerable) { this.enumerator = enumerable.GetEnumerator(); } public bool HasNext() { return enumerator.MoveNext(); } public T Next() { return enumerator.Current; } public void Remove() { throw new NotSupportedException(); } } //外觀模式的相關測試類 public class Amplifier { public void On() { Console.WriteLine("Top-0-Line Amplifier on"); } public void SetDvd(DvdPlayer dvd) { Console.WriteLine("Top-0-Line Amplifier setting DVD player to Top-0-Line DVD Player"); } public void SetVolume(int i) { Console.WriteLine("Top-0-Line Amplifier surround sound on (5 seakers, 1 subwoofer)"); Console.WriteLine("Top-0-Line Amplifier setting volume to 5"); } public void Off() { Console.WriteLine("Top-0-Line Ampliier off"); } } public class CdPlayer { } public class Doors { public void Lock() { } } public class DvdPlayer { private string movie; public void On() { Console.WriteLine("Top-0-Line DVD Player on"); } public void Play(string movie) { this.movie = movie; Console.WriteLine("Top-0-Line DVD Player playing \"{0}\"", movie); } public void Stop() { Console.WriteLine("Top-0-Line DVD Player stopped \"{0}\"", movie); } public void Eject() { Console.WriteLine("Top-0-Line DVD Player eject"); } public void Off() { Console.WriteLine("Top-0-Line DVD Player off"); } } public class Engine { public void Start() { } } public class PopcornPopper { public void On() { Console.WriteLine("Popcorn Popper on"); } public void Pop() { Console.WriteLine("Popcorn popper popping popcorn!"); } public void Off() { Console.WriteLine("Popcorn Popper off"); } } public class Projector { public void On() { Console.WriteLine("Top-0-Line Projector on"); } public void WideScreenMode() { Console.WriteLine("Top-0-Line Projector in widescreen mode (19*9 aspect ratio)"); } public void Off() { Console.WriteLine("Top-0-Line Projector off"); } } public class Screen { public void Down() { Console.WriteLine("Theater Screen going down"); } public void Up() { Console.WriteLine("Theater Screen going up"); } } public class TheaterLights { public void Dim(int i) { Console.WriteLine("Theater Ceiling Lights dimming to {0}%", i); } public void On() { Console.WriteLine("Theater Ceiling Lights on"); } } public class Tuner { } public class HomeTheaterFacade { private Amplifier amp; private Tuner tuner; private DvdPlayer dvd; private CdPlayer cd; private Projector projector; private TheaterLights lights; private Screen screen; private PopcornPopper popper; public HomeTheaterFacade(Amplifier amp, Tuner tuner, DvdPlayer dvd, CdPlayer cd, Projector projector, TheaterLights lights, Screen screen, PopcornPopper popper) { this.amp = amp; this.tuner = tuner; this.dvd = dvd; this.cd = cd; this.projector = projector; this.lights = lights; this.screen = screen; this.popper = popper; } public void WatchMovie(string movie) { Console.WriteLine("Get ready to watch a movie..."); popper.On(); popper.Pop(); lights.Dim(10); screen.Down(); projector.On(); projector.WideScreenMode(); amp.On(); amp.SetDvd(dvd); amp.SetVolume(5); dvd.On(); dvd.Play(movie); } public void EndMovie() { Console.WriteLine("Shutting movie theathe down..."); popper.Off(); lights.On(); screen.Up(); projector.Off(); amp.Off(); dvd.Stop(); dvd.Eject(); dvd.Off(); } } //執行測試 [Test] public void HomeTheaterTestDrive() { Amplifier amp = new Amplifier(); Tuner tuner = new Tuner(); DvdPlayer dvd = new DvdPlayer(); CdPlayer cd = new CdPlayer(); Projector projector = new Projector(); Screen screen = new Screen(); TheaterLights lights = new TheaterLights(); PopcornPopper popper = new PopcornPopper(); HomeTheaterFacade homeTheater = new HomeTheaterFacade(amp, tuner, dvd, cd, projector, lights, screen, popper); homeTheater.WatchMovie("Raiders of the lost ark"); homeTheater.EndMovie(); }
------------------------以上內容根據《Head First Design Mode》進行整理