摘要:適配器模式將一個(gè)類的接口轉(zhuǎn)換成客戶希望的另外一個(gè)接口。代理模式為其他對(duì)象提供一種代理以控制對(duì)這個(gè)對(duì)象的訪問(wèn)。如果用來(lái)解決排序問(wèn)題不符合開閉原則,添加策略需要修改代碼用策略模式將策略抽象成接口,不同的策略實(shí)現(xiàn)該接口。
簡(jiǎn)單工廠、工廠方法、抽象工廠 簡(jiǎn)單工廠
通過(guò)定義多個(gè)factory.produceXXX()方法,或者通過(guò)向factory.produce(type)傳遞type參數(shù)來(lái)生成產(chǎn)品。
添加新產(chǎn)品需要添加produeXXX()方法或個(gè)性produce(type)來(lái)支持生成新的產(chǎn)品。
一個(gè)Factory接口,接口中有一個(gè)produce()方法用于生成產(chǎn)品,具體的XXXFactory實(shí)現(xiàn)Factory接口并實(shí)現(xiàn)自己的produce()方法。
添加新產(chǎn)品時(shí)新增一個(gè)XXXFactory類,實(shí)現(xiàn)Factory接口并實(shí)現(xiàn)produce()方法。
一個(gè)Factory接口,接口中有多個(gè)produce()方法(produceA, produceB)每個(gè)方法對(duì)應(yīng)生成一個(gè)類產(chǎn)品。
XXXFactory實(shí)現(xiàn)Factory接口,并實(shí)現(xiàn)其中的produce*()方法。
抽象工廠與工廠方法的區(qū)別,可以理解為抽象工廠用于生產(chǎn)多個(gè)產(chǎn)品類,工廠方法只生產(chǎn)一個(gè)產(chǎn)品類。
保證一個(gè)類僅有一個(gè)實(shí)例,并提供一個(gè)靜態(tài)的getInstance()方法獲取這個(gè)實(shí)例。
懶漢式,不加鎖,線程不安全public class Singleton { private static Singleton instance; private Singleton (){} public static Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } }懶漢式,加鎖,線程安全
public class Singleton { private static Singleton instance; private Singleton (){} public static synchronized Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } }餓漢式,線程安全
public class Singleton {
private static Singleton instance = new Singleton(); private Singleton (){} public static Singleton getInstance() { return instance; }
}
懶漢式,雙重檢查,線程安全public class Singleton { private volatile static Singleton singleton; private Singleton (){} public static Singleton getSingleton() { if (singleton == null) { synchronized (Singleton.class) { if (singleton == null) { singleton = new Singleton(); } } } return singleton; } }懶漢式,靜態(tài)內(nèi)部類
public class Singleton { private static class SingletonHolder { private static final Singleton INSTANCE = new Singleton(); } private Singleton (){} public static final Singleton getInstance() { return SingletonHolder.INSTANCE; } }通過(guò)枚舉來(lái)實(shí)現(xiàn)單例
public enum Singleton { INSTANCE; public void whateverMethod() { } }
自由序列化,線程安全,保證單例。
建造者模式獨(dú)立的Builder類,通過(guò)build方法來(lái)生成實(shí)例。在build之前用add、set等一系列方法為將要生成的類設(shè)置屬性值。可以參考protobuf的對(duì)象創(chuàng)建方法。
原型模式復(fù)制現(xiàn)有實(shí)例生成新的實(shí)例。復(fù)制方式有深克隆與淺克隆之分,具體看clone()方法的實(shí)現(xiàn)。
適配器模式將一個(gè)類的接口轉(zhuǎn)換成客戶希望的另外一個(gè)接口。適配器模式使得原本由于接口不兼容而不能一起工作的那些類可以一起工作。
例:AudioPlayer.play()能能播放MP3,現(xiàn)在要它能播放其他格式(例如aac),另一個(gè)AACPlayer可以播放aac格式。實(shí)現(xiàn)方法:
1,創(chuàng)建一個(gè)MediaAdapter類,其中實(shí)例化一個(gè)AACPlayer用來(lái)播放aac格式
2,MediaAdapter實(shí)現(xiàn)play方法來(lái)調(diào)用AACPlayer的play方法,以此來(lái)實(shí)現(xiàn)適配
3,當(dāng)用AudioPlayer播放aac格式時(shí),調(diào)用MediaAdapter.play來(lái)間接調(diào)用AACPlayer的play方法
4,要用AudioPlayer播放所有其他格式,都在MediaAdapter中做適配。
將抽象和實(shí)現(xiàn)放在兩個(gè)不同的類層次中,使它們可以獨(dú)立地變化。——《Head First 設(shè)計(jì)模式》
如何理解:
Bridge.java
public interface Bridge { public void func(int radius, int x, int y); }
TheAbastractClass.java
public abstract class TheAbstractClass { protected Bridge bridge; protected TheAbstractClass(Bridge bridge){ this.bridge = bridge; } public abstract void func(); }
BridgeOne.java
public class BridgeOne implements Bridge { @Override public void func() { System.out.println("BridgeOne.func called!"); } }
BridgeTwo.java
public class BridgeTwo implements Bridge { @Override public void func() { System.out.println("BridgeTwo.func called!"); } }
TheSpecificClass.java
public class TheSpecificClass extends TheAbastractClass{ TheSpecificClass(Bridge bridge){ super(bridge); } @override public void func(){ this.bridge.func(); } }
一般來(lái)說(shuō),直接繼承TheAbstractClass來(lái)實(shí)現(xiàn)func方法。在橋模式下,繼承TheAbstractClass之后,func方法的具體實(shí)現(xiàn)則在通過(guò)this.bridge實(shí)現(xiàn)的。
橋模式和適配器模式的區(qū)別可以看這篇文章
類似函數(shù)式編程中的filter
組合模式對(duì)象中包含對(duì)象,用實(shí)現(xiàn)樹型結(jié)構(gòu),對(duì)單個(gè)對(duì)象和組合對(duì)象的使用具有一致性。
裝飾模式用于動(dòng)態(tài)地給一個(gè)對(duì)象添加一些額外的職責(zé)。
例:
Origin.java
public interface Origin{ void func(); }
OriginImpl.java
public class OriginImpl implements Origin{ public void func() { //do something } }
AbstactDecorator.java
public abstract class AbstractDecorator implements Origin{ protect Origin origin; public AbstractDecorator(Origin origin){ this.origin = origin; } public void func(){ this.origin.func(); } }
SpecificDecorator.java
public class SpecificeDecorator extends AbstractDecorator{ public SpecificDecorator(Origin origin){ super(origin); } @Override public void func(){ this.origin.func(); //do something else } }
main
public static int main(){ Origin origin = new SpecificeDecorator(new OriginImpl()); origin.func(); }
通過(guò)裝飾器SpecificDecorator,可以在原來(lái)的OriginImpl.func()的基礎(chǔ)上do something else
外觀模式用于隱藏系統(tǒng)的復(fù)雜性,提供一致的操作界面。
例如:
1,ClassA, ClassB, ClassC三個(gè)類分別有methodA, methodB, methodC三個(gè)方法
2,創(chuàng)建Facade類,關(guān)聯(lián)ClassA, ClassB, ClassC,提供methodA, methodB, mehtodC
3,通過(guò)Facade就可以調(diào)用mehtodA, methodB, methodC了
就是共享對(duì)象,將原來(lái)創(chuàng)建的對(duì)象保存起來(lái),下次需要使用的時(shí)候優(yōu)先使用已經(jīng)創(chuàng)建過(guò)的相同對(duì)象。
代理模式為其他對(duì)象提供一種代理以控制對(duì)這個(gè)對(duì)象的訪問(wèn)。
Origin.java
public interface Origin{ void func(); }
OriginImpl.java
public class OriginImpl implements Origin{ public void func() { //do something } }
Proxy.java
public class Proxy implements Origin{ private Origin origin; public void func(){ if(origin == null){ origin = new OriginImpl(); } this.origin.func(); } }
Proxy為代理類,通過(guò)Proxy來(lái)間接的調(diào)用OriginImpl.func()
責(zé)任鏈模式將請(qǐng)求的發(fā)送者和請(qǐng)求的處理者解耦。
當(dāng)有多種類型(type)的Request,每個(gè)Request有一個(gè)指定的handler,通過(guò)把所有的handler連接起來(lái)形成一條鏈handlerLink。請(qǐng)求可以不用發(fā)送到指定的handler,直接發(fā)送到handlerLink,鏈中的每個(gè)handler判斷type是不是自己的要處理的,如果不是則傳遞到下一個(gè)handler
對(duì)命令請(qǐng)求者(Invoker)和命令實(shí)現(xiàn)者(Receiver)的解耦,方便對(duì)命令進(jìn)行各種控制。
ICommand: 命令接口,有execute方法
Command: 命令實(shí)現(xiàn)類
Invoker: 請(qǐng)求發(fā)送者
Receiver: 請(qǐng)求接收者,負(fù)責(zé)執(zhí)行實(shí)際的業(yè)務(wù)邏輯
不用命令模式:
想要調(diào)用Receiver的doSomething()方法
Receiver r = new Receiver(); r.doSomething()
命令模式:
Command.java
public Interface ICommand{ void execute(); } public class Command implements ICommand{ private Receiver receiver; public Command(Receiver receiver){ this.receiver = receiver; } public void execute(){ receiver.doSomething(); } }
Invoker.java
public class Invoker{ ICommand cmd; public void setCommand(ICommand cmd){ this.cmd = cmd; } public void submit(){ this.cmd.execute(); } }
main
Invoker invoker = new Invoker(); Receiver receiver = new Receiver(); ICommand cmd = new Command(receiver); invoker.setCommand(cmd); invoder.submit();
命令模式實(shí)現(xiàn)Invoker與Receiver的隔離,Command與Receiver耦合。發(fā)送者只接收命令。當(dāng)要擴(kuò)展新的功能的時(shí)候,創(chuàng)建新的ICommand的實(shí)現(xiàn)類交給Invoker即可。
解釋器模式個(gè)人理解就是,解釋器的作用就是把人能看明白的東西解釋一下,讓機(jī)器也看明白。比如,python代碼是給人看的,python解釋器就是把代碼解釋成機(jī)器能執(zhí)行的指令;計(jì)算表達(dá)式(1+2+3*4/7)是人能看懂的,計(jì)算器的作用就是把計(jì)算表達(dá)式解釋成能執(zhí)行的一系列的簡(jiǎn)單運(yùn)算。
代碼和計(jì)算表達(dá)式這樣的問(wèn)題有幾個(gè)重要的特征:
用什么元素來(lái)書寫,在計(jì)算表達(dá)式中就是數(shù)字(0-9)和運(yùn)算符(+-*/),在代碼中就是字母、數(shù)字和符號(hào)
怎么書寫(文法),在計(jì)算表達(dá)式中運(yùn)算符和數(shù)字必須交替出現(xiàn),在代碼中就是各種語(yǔ)言和各自的語(yǔ)法規(guī)則。
所以,有規(guī)則可循的問(wèn)題都可以用解釋器模式來(lái)解決。但是將問(wèn)題的規(guī)則提煉出來(lái)是很麻煩的,而且規(guī)則很復(fù)雜的時(shí)候更加難以提煉,成本很高。因此,只有當(dāng)一類問(wèn)題發(fā)生的頻率足夠高的情況下才適合用解釋器模式。
迭代器模式為不同的數(shù)據(jù)結(jié)構(gòu)提供統(tǒng)一的順序遍歷的操作。
中介者模式假設(shè)有ABCD四個(gè)對(duì)象,如果兩兩交互的話每個(gè)對(duì)象要維護(hù)三條鏈路。
加入中介,每個(gè)對(duì)象維護(hù)一條鏈路。
保存歷史狀態(tài),以便可以恢復(fù)到原先的狀態(tài)。
觀察者模式使用場(chǎng)景:一個(gè)對(duì)象A的改變要通知到一個(gè)或多個(gè)其他對(duì)象。
加入觀察者可以讓A不必關(guān)心具體要通知改變的其他對(duì)象,由觀察者來(lái)發(fā)通知。
狀態(tài)模式類的行為是基于它的狀態(tài)改變的,允許對(duì)象在內(nèi)部狀態(tài)發(fā)生改變時(shí)改變它的行為,對(duì)象看起來(lái)好像修改了它的類。如何理解這句話?
類(TheClass), 狀態(tài)(State), 行為(action)
代碼:
public class TheClass{ private State state; public void action(){ //TODO depends on state } }
TODO這塊可以用switch case或者if else來(lái)實(shí)現(xiàn),State一般是一個(gè)int
typedef int State;//狀態(tài)一般是個(gè)整型 public class TheClass{ private State state; public void setState(State state){ this.state = state; } public void action(){ switch (state) { case stateA: //do A; case stateB: //do B; } } }
不符合開閉原則,因?yàn)槿绻黾右环N狀態(tài),則需要修改代碼,添加case
用狀態(tài)模式,State是一個(gè)interface, 擁有一個(gè)action方法
public interface State{ void action(); } public Class StateA implements State{ public void action(){ //do A } } public Class StateB implements State{ public void action(){ //do B } } public class TheClass{ private State state; public void setState(State state){ this.state = state; } public void action(){ this.state.action() } }
如果要添加一個(gè)C狀態(tài),只需要新建一個(gè)StateC實(shí)現(xiàn)State接口即可。
空對(duì)象模式對(duì)象有方法,NULL什么都沒有。空對(duì)象目的在于提供默認(rèn)的方法。這樣我們空對(duì)象執(zhí)行相關(guān)操作時(shí)也不會(huì)報(bào)錯(cuò)。
策略模式從輸入獲取輸出可以有多種策略,例如排序問(wèn)題就有插入、冒泡、快速、歸并等不同和策略,都可以得到相同的結(jié)果。各種策略分別適用于特定的輸入,例如,對(duì)于本身有序數(shù)組來(lái)說(shuō),冒泡策略只需要遍歷一遍就可以。
如果用if else來(lái)解決排序問(wèn)題:
sort(List list, Strategy strategy){ switch (strategy) { case insert: //do insert sort case bubble: //do bubble sort ... } }
不符合開閉原則,添加策略需要修改代碼
用策略模式:
sort(List list, Strategy strategy){ strategy.sort(list) }
將策略抽象成接口,不同的策略實(shí)現(xiàn)該接口。
模板模式一個(gè)操作operate,有多個(gè)step。我們把operate定義為固定的模板,各個(gè)step則可以重寫。
public abstract class Template{ void step1(); void step2(); void step3(); void final operate(){ step1(); step2(); step3(); } } public class TheClass extends Template{ @override void step1(){ //do step1 } void step2(){ //do step2 } void step3(){ //do step3 } }訪問(wèn)者模式
被訪問(wèn)者接口(Acceptor): 有accept(visitor)方法,接收visitor的訪問(wèn)
被訪元素(AcceptorItem): 實(shí)現(xiàn)了Acceptor接口,通常不會(huì)直接暴露給Visitor。
訪問(wèn)者(Visitor): 有visit(acceptor)方法,訪問(wèn)acceptor元素
被訪問(wèn)對(duì)象(Containor): 直接暴露給Visitor出來(lái)的被訪問(wèn)對(duì)象,相當(dāng)于一個(gè)Containor,以一定的結(jié)構(gòu)組織了各個(gè)AcceptorItem。
Acceptor.java
public interface Acceptor{ void acceptor(Visitor visitor); }
Visitor.java
public interface Visitor{ void visit(AcceptorOne acceptor); void visit(AcceptorTwo acceptor); }
AcceptorOne.java
public class AcceptorOne extends{ public void accept(Visitor visitor){ visitor.visit(this); } }
AcceptorTwo.java
public class AcceptorTwo extends{ public void accept(Visitor visitor){ visitor.visit(this); } }
Containor.java
public class Containor implements Acceptor{ private Collectionacceptors; public void accept(Visitor visitor){ Iteratro it = acceptors.getIterator(); while(it.hasNext()){ visitor.visit(it.next()); } } }
訪問(wèn)者(Vistor)有多個(gè)visit方法,visit根據(jù)不同的Accepctor執(zhí)行不同的邏輯。如果要擴(kuò)展新的Acceptor,需要修改Visitor接口,這樣不符合開閉原則;而擴(kuò)展新的Visitor時(shí),則只需要新增Visitor實(shí)現(xiàn)就可以了。因此,訪問(wèn)者模式適合對(duì)象結(jié)構(gòu)穩(wěn)定,而經(jīng)常需要擴(kuò)展對(duì)象操作的場(chǎng)景。
MVC模式MVC模式是一種軟件架構(gòu)模式,應(yīng)于交互式應(yīng)用中。交互式應(yīng)用就是界面+操作+數(shù)據(jù)后臺(tái)。如果不使用MVC模式,界面的代碼和對(duì)數(shù)據(jù)操作的代碼雜在一起,不方便重用,也不容易維護(hù)。MVC模式分離了界面和數(shù)據(jù),界面(View)通過(guò)控制器(Controller)提供的接口操作數(shù)據(jù)模型(Model),后臺(tái)數(shù)據(jù)變更之后通過(guò)控制器通知到相關(guān)的界面。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/73303.html
摘要:以下知識(shí)點(diǎn)是前輩師兄總結(jié)基礎(chǔ)語(yǔ)義化標(biāo)簽引進(jìn)了一些新的標(biāo)簽,特別注意等,注意的標(biāo)題結(jié)構(gòu)理解瀏覽器解析的過(guò)程,理解的樹形結(jié)構(gòu),及相應(yīng)理解標(biāo)簽在各個(gè)瀏覽器上的默認(rèn)樣式代理樣式,理解中的重置樣式表的概念理解等功能性標(biāo)簽理解標(biāo)簽,理解文件提交過(guò)程推薦 以下知識(shí)點(diǎn)是前輩師兄總結(jié) 1、HTML/HTML5基礎(chǔ): 1.0、語(yǔ)義化H5標(biāo)簽1.1、H5引進(jìn)了一些新的標(biāo)簽,特別注意article...
摘要:以下知識(shí)點(diǎn)是前輩師兄總結(jié)基礎(chǔ)語(yǔ)義化標(biāo)簽引進(jìn)了一些新的標(biāo)簽,特別注意等,注意的標(biāo)題結(jié)構(gòu)理解瀏覽器解析的過(guò)程,理解的樹形結(jié)構(gòu),及相應(yīng)理解標(biāo)簽在各個(gè)瀏覽器上的默認(rèn)樣式代理樣式,理解中的重置樣式表的概念理解等功能性標(biāo)簽理解標(biāo)簽,理解文件提交過(guò)程推薦 以下知識(shí)點(diǎn)是前輩師兄總結(jié) 1、HTML/HTML5基礎(chǔ): 1.0、語(yǔ)義化H5標(biāo)簽1.1、H5引進(jìn)了一些新的標(biāo)簽,特別注意article...
摘要:更好的理解設(shè)計(jì)模式我覺得對(duì)于設(shè)計(jì)模式的理解是把設(shè)計(jì)模式歸并到架構(gòu)的一部分,是架構(gòu)的子集,重命名為代碼架構(gòu),這樣好理解很多。 設(shè)計(jì)模式,這是我聽過(guò)最糟糕的翻譯,這個(gè)名字對(duì)于程序員來(lái)說(shuō)有點(diǎn)高高在上,難以理解,尤其是php,python,nodejs這些腳本語(yǔ)言的開發(fā)人員可能因?yàn)檫@個(gè)名字就忽視了設(shè)計(jì)模式的重要性。當(dāng)然,除了名字以外,從更深層次,更具體來(lái)說(shuō),我覺得有三個(gè)原因: 不用設(shè)計(jì)模式也...
摘要:更好的理解設(shè)計(jì)模式我覺得對(duì)于設(shè)計(jì)模式的理解是把設(shè)計(jì)模式歸并到架構(gòu)的一部分,是架構(gòu)的子集,重命名為代碼架構(gòu),這樣好理解很多。 設(shè)計(jì)模式,這是我聽過(guò)最糟糕的翻譯,這個(gè)名字對(duì)于程序員來(lái)說(shuō)有點(diǎn)高高在上,難以理解,尤其是php,python,nodejs這些腳本語(yǔ)言的開發(fā)人員可能因?yàn)檫@個(gè)名字就忽視了設(shè)計(jì)模式的重要性。當(dāng)然,除了名字以外,從更深層次,更具體來(lái)說(shuō),我覺得有三個(gè)原因: 不用設(shè)計(jì)模式也...
摘要:在他的重學(xué)前端課程中提到到現(xiàn)在為止,前端工程師已經(jīng)成為研發(fā)體系中的重要崗位之一。大部分前端工程師的知識(shí),其實(shí)都是來(lái)自于實(shí)踐和工作中零散的學(xué)習(xí)。一基礎(chǔ)前端工程師吃飯的家伙,深度廣度一樣都不能差。 開篇 前端開發(fā)是一個(gè)非常特殊的行業(yè),它的歷史實(shí)際上不是很長(zhǎng),但是知識(shí)之繁雜,技術(shù)迭代速度之快是其他技術(shù)所不能比擬的。 winter在他的《重學(xué)前端》課程中提到: 到現(xiàn)在為止,前端工程師已經(jīng)成為研...
摘要:在他的重學(xué)前端課程中提到到現(xiàn)在為止,前端工程師已經(jīng)成為研發(fā)體系中的重要崗位之一。大部分前端工程師的知識(shí),其實(shí)都是來(lái)自于實(shí)踐和工作中零散的學(xué)習(xí)。一基礎(chǔ)前端工程師吃飯的家伙,深度廣度一樣都不能差。開篇 前端開發(fā)是一個(gè)非常特殊的行業(yè),它的歷史實(shí)際上不是很長(zhǎng),但是知識(shí)之繁雜,技術(shù)迭代速度之快是其他技術(shù)所不能比擬的。 winter在他的《重學(xué)前端》課程中提到: 到現(xiàn)在為止,前端工程師已經(jīng)成為研發(fā)體系...
閱讀 2415·2021-09-01 10:41
閱讀 1440·2019-08-30 14:12
閱讀 507·2019-08-29 12:32
閱讀 2856·2019-08-29 12:25
閱讀 2934·2019-08-28 18:30
閱讀 1704·2019-08-26 11:47
閱讀 973·2019-08-26 10:35
閱讀 2587·2019-08-23 18:06