摘要:適配器模式不應(yīng)在設(shè)計(jì)階段考慮,它是為了解決已經(jīng)上線的問題的存在。組合模式將對(duì)象組合成樹形結(jié)構(gòu)以表示部分整體的層次結(jié)構(gòu),使得用戶對(duì)單個(gè)對(duì)象和組合對(duì)象的使用具有一致性。
代理模式
代理模式之前已經(jīng)講過(guò),附上鏈接代理模式
裝飾者模式裝飾者模式定義:動(dòng)態(tài)地給一個(gè)對(duì)象添加一些額外的職責(zé)。就增加功能來(lái)說(shuō),裝飾模式相比生成子類更為靈活。
裝飾模式博主在第一次學(xué)習(xí)是懵逼的,是因?yàn)榇砟J街写韺?duì)象和目標(biāo)對(duì)象都實(shí)現(xiàn)了同一個(gè)接口,裝飾者模式中裝飾對(duì)象和被裝飾對(duì)象也都實(shí)現(xiàn)了同一個(gè)接口,并且都可以很容易的在方法前面或后面增加一些功能來(lái)達(dá)到增強(qiáng)方法的目的。其實(shí)裝飾模式就是代理模式的一個(gè)特殊應(yīng)用,兩者的共同點(diǎn)是都實(shí)現(xiàn)了同一個(gè)接口,不同點(diǎn)就是代理模式著重對(duì)代理過(guò)程的控制,而裝飾模式是對(duì)類的功能進(jìn)行增強(qiáng)或減弱,它著重類的功能變化。
java的規(guī)范必然是jdk源碼了,學(xué)習(xí)裝飾者模式一定要看下io的實(shí)現(xiàn)。io是負(fù)責(zé)讀取數(shù)據(jù)的,而數(shù)據(jù)的來(lái)源又分為文件、字節(jié)數(shù)組、字符緩沖區(qū)、線程輸入流、序列化的對(duì)象等等。如下圖所示:
圖有點(diǎn)丑....輸入流讀取數(shù)據(jù)按照數(shù)據(jù)來(lái)源已經(jīng)分成五類,按理來(lái)說(shuō)應(yīng)該夠用了,那為什么還會(huì)有BufferedInputStream,DataInputStream,PushbackInputStream呢?我們拿bufferinputstream來(lái)分析,因?yàn)閕o流讀取是訪問硬盤,硬盤的訪問速度在計(jì)算機(jī)的世界里一定是極慢的,也是極其耗資源的,為了解決這個(gè)問題,發(fā)明了BufferedInputStream,先讀取buffer,實(shí)在找不到再去硬盤里找。那我們?cè)趺磳⑵浼尤氲絠o家族中呢?如果我們給每種io流增加子類,使其擁有讀取buffer的能力,那么僅以圖中展示出來(lái)的,就要加5個(gè)子類,加上DataInputStream(byte轉(zhuǎn)成java數(shù)據(jù)類型),PushbackInputStream(讀取之后寫回流)那就是15個(gè)子類,已經(jīng)形成了類爆炸的問題,任誰(shuí)看到都是頭大的...
加入我們需要一個(gè)既可以讀buffer又可以將數(shù)據(jù)轉(zhuǎn)成java類型的輸入流,正確的姿勢(shì)是這樣的:
//InputStream inputStream = new BufferedInputStream(new DataInputStream(new FileInputStream(""))); BufferedInputStream inputStream = new BufferedInputStream(new DataInputStream(new FileInputStream("")));
從這里就可以看出來(lái)裝飾者模式和依賴倒置原則是有點(diǎn)沖突的,因?yàn)橐蕾嚨怪迷瓌t讓我們依賴抽象,說(shuō)白了就是面向接口編程,如果我們面向接口使用InputStream聲明,它依然無(wú)法擁有緩存的能力,這證明了想要找出一段完全符合六大設(shè)計(jì)模式的代碼是很難的...
適配器模式將一個(gè)類的接口變換成客戶端所期待的另一種接口,從而使原本因接口不匹配而無(wú)法在一起工作的兩個(gè)類能夠一起工作。
適配器模式最好在設(shè)計(jì)階段不要考慮它,他不是為了解決開發(fā)階段存在的問題,而是解決已經(jīng)上線的項(xiàng)目問題。任何一個(gè)架構(gòu)師都不應(yīng)該在設(shè)計(jì)階段考慮使用適配器模式,并且項(xiàng)目一定要嚴(yán)格遵守依賴倒置原則和里氏替換原則,適配器模式才會(huì)帶給你巨大的好處,否則即使在適合用適配器模式的情況下,也會(huì)給項(xiàng)目帶來(lái)巨大改造。
現(xiàn)在假設(shè)這樣一個(gè)場(chǎng)景,A公司收購(gòu)了B公司,要對(duì)B公司的用戶數(shù)據(jù)和項(xiàng)目進(jìn)行一個(gè)內(nèi)部消化,但兩個(gè)系統(tǒng)的實(shí)現(xiàn)又不一樣,如何最小的改動(dòng)最優(yōu)的整合到一起呢?我們拿用戶模塊來(lái)看下,A公司的用戶是這樣設(shè)計(jì)的:
public interface IUserInfo { String getName(); String getSex(); void getMobile(); }
public class UserInfo implements IUserInfo { @Override public String getName() { System.out.println("老子是光頭強(qiáng)"); } @Override public String getSex() { System.out.println("老子是男性"); } @Override public String getMobile() { System.out.println("手機(jī)號(hào):12345678"); } }
B公司用戶模塊是這樣設(shè)計(jì)的:
public interface IUserDetail { Map getUserBaseinfo(); }
public class UserDetail implements IUserDetail { private Map map; @Override public Map getUserBaseinfo() { map = new HashMap(); map.put("name","張三"); map.put("sex","男"); map.put("phone","1896369448"); return null; } }
首先我們的系統(tǒng)要和他們的系統(tǒng)進(jìn)行交互,不可能為了這一小小的功能對(duì)我們已經(jīng)良好運(yùn)行的項(xiàng)目進(jìn)行大改動(dòng),那怎么辦呢?只能轉(zhuǎn)化了,拿到對(duì)方的數(shù)據(jù)對(duì)象然后轉(zhuǎn)化為我們自己的數(shù)據(jù)對(duì)象。設(shè)計(jì)是這樣子的:
public class NewUser extends UserDetail implements IUserInfo { @Override public String getName() { String name = (String) super.getUserBaseinfo().get("name"); System.out.println(name); return name; } @Override public String getSex() { return (String) super.getUserBaseinfo().get("sex"); } @Override public String getMobile() { return (String) super.getUserBaseinfo().get("mobile"); } }
測(cè)試類是這樣的:
//大boss獲取A公司人員的手機(jī)號(hào),臨時(shí)反悔想要B公司人員的手機(jī)號(hào) public class Client { // public static void main(String[] args) { //IUserInfo userInfo = new UserInfo(); //userInfo.getMobile(); //} public static void main(String[] args) { //臨時(shí)改變主意獲取B公司人員的手機(jī)號(hào) IUserInfo userInfo1 = new NewUser(); userInfo1.getMobile(); } }
使用適配器模式只修改了一句話,其他的業(yè)務(wù)邏輯不用修改就既覺了對(duì)接的問題。適配器可以讓兩個(gè)沒有任何關(guān)系的類在一起運(yùn)行,只要適配器這個(gè)角色能搞定他們就行。適用適配器模式的場(chǎng)景只要記住一點(diǎn)就夠了:當(dāng)你要去修改一個(gè)已經(jīng)投入到生產(chǎn)當(dāng)中的接口,適配器模式可能是最適合你的模式了。適配器模式不應(yīng)在設(shè)計(jì)階段考慮,它是為了解決已經(jīng)上線的問題的存在。
門面模式要求一個(gè)子系統(tǒng)的外部與其內(nèi)部的通信必須通過(guò)一個(gè)統(tǒng)一的對(duì)象進(jìn)行。門面模式提供一個(gè)高層次的接口,使得子系統(tǒng)更易于使用。
門面模式注重統(tǒng)一的對(duì)象,提供一個(gè)訪問子系統(tǒng)的接口,除了這個(gè)接口不允許有任何訪問子系統(tǒng)的行為發(fā)生。門面對(duì)象是外界訪問子系統(tǒng)內(nèi)部的唯一通道,不管子系統(tǒng)內(nèi)部多么雜亂無(wú)章,只要門面對(duì)象在,就可以做到"金玉其外,敗絮其中"。
源碼中應(yīng)用此模式的非常多,slf4j使用的就是此模式。這是一個(gè)簡(jiǎn)單的設(shè)計(jì)模式,直接給大家上例子:
public interface Drink { void drink(); }
public class Milk implements Drink { @Override public void drink() { System.out.println("喝牛奶"); } }
public class RedTea implements Drink { @Override public void drink() { System.out.println("喝紅茶"); } }
public class Water implements Drink { @Override public void drink() { System.out.println("喝涼白開"); } }
public class Facade { private Milk milk = new Milk(); private RedTea redTea = new RedTea(); private Water water = new Water(); public void drinkMilk(){ milk.drink(); } public void drinkRedTea(){ redTea.drink(); } public void drinkWater(){ water.drink(); } }
統(tǒng)一的對(duì)象指的就是門面,也就是上述例子中的facade。
門面模式可以減少系統(tǒng)間的互相依賴,因?yàn)樗械囊蕾嚩际且蕾囉陂T面對(duì)象,與子系統(tǒng)的業(yè)務(wù)無(wú)關(guān)。只依賴門面對(duì)象,也就是說(shuō)子系統(tǒng)的業(yè)務(wù)如何變化只要不影響到門面對(duì)象,大大提高了靈活性。缺點(diǎn)就是過(guò)于依賴門面對(duì)象,不符合開閉原則,一旦門面對(duì)象中出現(xiàn)錯(cuò)誤,對(duì)子系統(tǒng)的打擊是非常大的,修改門面對(duì)象時(shí),一定要慎之又慎。
將對(duì)象組合成樹形結(jié)構(gòu)以表示“部分-整體”的層次結(jié)構(gòu),使得用戶對(duì)單個(gè)對(duì)象和組合對(duì)象的使用具有一致性。
概念有點(diǎn)抽象,但其實(shí)很簡(jiǎn)單。相信大部分猿都用過(guò),只是不知道他還有這個(gè)名字罷了。簡(jiǎn)單的模式不啰嗦,直接上例子:
public class Person { private String name; private String age; private Listlist = new ArrayList<>(); public void addPerson(){ list.add(new Person()); } public void removePerson(Person person){ list.remove(person); } public Person getChild(int i){ return list.get(i); } }
每個(gè)人都有年齡和姓名,每個(gè)人也都會(huì)有孩子。構(gòu)造成樹形結(jié)構(gòu),使單個(gè)對(duì)象和組合對(duì)象的訪問具有一致性。模式很簡(jiǎn)單,不浪費(fèi)大家時(shí)間。
享元模式使用共享對(duì)象可有效的支持大量的細(xì)粒度的對(duì)象。
享元模式是池技術(shù)實(shí)現(xiàn)的核心思想。其核心概念有共享對(duì)象和細(xì)粒度的對(duì)象.細(xì)粒度的對(duì)象的特點(diǎn)就是對(duì)象數(shù)量多切性質(zhì)相近,我們應(yīng)將其不變的部分抽出來(lái)形成共享對(duì)象,存放在池中,減少內(nèi)存使用.復(fù)用對(duì)象最簡(jiǎn)單的方式是,用一個(gè) HashMap 來(lái)存放每次新生成的對(duì)象。每次需要一個(gè)對(duì)象的時(shí)候,先到 HashMap 中看看有沒有,如果沒有,再生成新的對(duì)象,然后將這個(gè)對(duì)象放入 HashMap 中.代碼很簡(jiǎn)單,不在舉例.
橋梁模式將抽象和實(shí)現(xiàn)解耦,使得兩者可以獨(dú)立的變化。
橋梁模式的關(guān)鍵點(diǎn)在于解耦?,F(xiàn)在的公司有很多,我們今天拿互聯(lián)網(wǎng)公司和外包公司來(lái)舉例。每個(gè)公司會(huì)有很多部門,每個(gè)部門工作的方式又不一樣,模式很簡(jiǎn)單,直接上例子:
//抽象部門接口,用來(lái)定義要實(shí)現(xiàn)的方法 public interface IDepartment { //每個(gè)部門都要工作,公司請(qǐng)你不是來(lái)吃閑飯的 void work(); }
//苦逼的程序員 public class Coder implements IDepartment { @Override public void work() { System.out.println("程序猿工作:將咖啡變成代碼"); } }
//苦逼的測(cè)試 public class QA implements IDepartment { @Override public void work() { System.out.println("測(cè)試:保證產(chǎn)品質(zhì)量"); } }
//it公司 public abstract class ITCompany { //引入部門抽象 private IDepartment iDepartment; public ITCompany(IDepartment iDepartment) { this.iDepartment = iDepartment; } public void work(){ iDepartment.work(); } } //互聯(lián)網(wǎng)公司 class InternetCompany extends ITCompany{ public InternetCompany(IDepartment iDepartment) { super(iDepartment); } } //外包公司 class outerPackCompany extends ITCompany{ public outerPackCompany(IDepartment iDepartment) { super(iDepartment); } }
public class Client { public static void main(String[] args) { ITCompany itCompany = new InternetCompany(new Coder()); itCompany.work(); ITCompany outerPackCompany = new outerPackCompany(new QA()); outerPackCompany.work(); } }
怎么樣,很簡(jiǎn)單把。它的重點(diǎn)就是解耦,符合開閉原則和依賴倒置原則。在此架構(gòu)的基礎(chǔ)上,我們不管是想要增加抽象還是具體實(shí)現(xiàn)類都是易如反掌。橋梁模式的意圖就是對(duì)變化的封裝,把可能變化的封裝到最小的邏輯單元,避免風(fēng)險(xiǎn)擴(kuò)散.
總結(jié)設(shè)計(jì)模式到此就算告一段落了。學(xué)習(xí)設(shè)計(jì)模式可以有助于我們寫出優(yōu)雅、易維護(hù)、易擴(kuò)展的代碼,也可以讓我們更好的理解源碼。為了寫設(shè)計(jì)模式的文章,看了兩三本關(guān)于設(shè)計(jì)模式的書,翻閱了許多資料,講的不是特別好,但總歸可以帶大家入門。若是大家想看書學(xué)習(xí),按照難度從低到高可自行選擇:<大話設(shè)計(jì)模式>、<設(shè)計(jì)模式之禪>、gof的<設(shè)計(jì)模式>.
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/68380.html
面試舊敵之紅黑樹(直白介紹深入理解) - Android - 掘金 讀完本文你將了解到: 什么是紅黑樹 黑色高度 紅黑樹的 5 個(gè)特性 紅黑樹的左旋右旋 指定節(jié)點(diǎn) x 的左旋 右圖轉(zhuǎn)成左圖 指定節(jié)點(diǎn) y 的右旋左圖轉(zhuǎn)成右圖 紅黑樹的平衡插入 二叉查找樹的插入 插入后調(diào)整紅黑樹結(jié)構(gòu) 調(diào)整思想 插入染紅后... java 多線程同步以及線程間通信詳解 & 消費(fèi)者生產(chǎn)者模式 & 死鎖 & Thread...
摘要:新的數(shù)據(jù)表關(guān)系數(shù)據(jù)的數(shù)據(jù)結(jié)構(gòu)類似于這樣子大碼中碼小碼這個(gè)表結(jié)構(gòu)的說(shuō)明是避免對(duì)于關(guān)系鏈的數(shù)據(jù)邏輯不理解做的一個(gè)示例。 最近幾天一直在糾結(jié)于一個(gè)大數(shù)據(jù)批量導(dǎo)入的問題,經(jīng)過(guò)幾天思考,發(fā)現(xiàn)基于小數(shù)據(jù)情況,原本的數(shù)據(jù)結(jié)構(gòu)設(shè)計(jì)是沒有問題的,但是在大量數(shù)據(jù)導(dǎo)入,問題就很大了。我之前一直在強(qiáng)調(diào)程序=數(shù)據(jù)結(jié)構(gòu)+算法,但在這此卻鉆了牛角尖,最后去仔細(xì)看了之前別人設(shè)計(jì)的數(shù)據(jù)表才突然靈光一現(xiàn),發(fā)現(xiàn)了mysql...
摘要:可以說(shuō),如果問題是我們的敵人,代碼是我們的劍,設(shè)計(jì)模式就是高手心中的劍譜。中級(jí)選手,在編程的時(shí)候知道何時(shí)該用什么設(shè)計(jì)模式,而什么時(shí)候不該用。設(shè)計(jì)模式被用來(lái)簡(jiǎn)化設(shè)計(jì),讓設(shè)計(jì)更優(yōu)雅。其中最具有普遍性的方案往往就是我們的設(shè)計(jì)模式的內(nèi)容。 showImg(https://segmentfault.com/img/remote/1460000019100076?w=800&h=440); 目錄概...
閱讀 2079·2021-11-24 09:39
閱讀 802·2021-09-30 09:48
閱讀 989·2021-09-22 15:29
閱讀 2429·2019-08-30 14:17
閱讀 1898·2019-08-30 13:50
閱讀 1356·2019-08-30 13:47
閱讀 990·2019-08-30 13:19
閱讀 3430·2019-08-29 16:43