理解設計模式

簡單工廠、工廠方法、抽象工廠

簡單工廠

經過定義多個factory.produceXXX()方法,或者經過向factory.produce(type)傳遞type參數來生成產品。
添加新產品須要添加produeXXX()方法或個性produce(type)來支持生成新的產品。html

工廠方法

一個Factory接口,接口中有一個produce()方法用於生成產品,具體的XXXFactory實現Factory接口並實現本身的produce()方法。
添加新產品時新增一個XXXFactory類,實現Factory接口並實現produce()方法。java

抽象工廠

一個Factory接口,接口中有多個produce()方法(produceA, produceB)每一個方法對應生成一個類產品。
XXXFactory實現Factory接口,並實現其中的produce*()方法。
抽象工廠與工廠方法的區別,能夠理解爲抽象工廠用於生產多個產品類,工廠方法只生產一個產品類。python

單例模式

保證一個類僅有一個實例,並提供一個靜態的getInstance()方法獲取這個實例。編程

懶漢式,不加鎖,線程不安全

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;  
    }  
}

懶漢式,靜態內部類

public class Singleton {  
    private static class SingletonHolder {  
        private static final Singleton INSTANCE = new Singleton();  
    }  
    private Singleton (){}  
    public static final Singleton getInstance() {  
        return SingletonHolder.INSTANCE;  
    }  
}

經過枚舉來實現單例

public enum Singleton {  
    INSTANCE;  
    public void whateverMethod() {  
    }  
}

自由序列化,線程安全,保證單例。安全

建造者模式

獨立的Builder類,經過build方法來生成實例。在build以前用add、set等一系列方法爲將要生成的類設置屬性值。能夠參考protobuf的對象建立方法。數據結構

原型模式

複製現有實例生成新的實例。複製方式有深克隆與淺克隆之分,具體看clone()方法的實現。架構

適配器模式

將一個類的接口轉換成客戶但願的另一個接口。適配器模式使得本來因爲接口不兼容而不能一塊兒工做的那些類能夠一塊兒工做。
例:AudioPlayer.play()能能播放MP3,如今要它能播放其餘格式(例如aac),另外一個AACPlayer能夠播放aac格式。實現方法:
1,建立一個MediaAdapter類,其中實例化一個AACPlayer用來播放aac格式
2,MediaAdapter實現play方法來調用AACPlayer的play方法,以此來實現適配
3,當用AudioPlayer播放aac格式時,調用MediaAdapter.play來間接調用AACPlayer的play方法
4,要用AudioPlayer播放全部其餘格式,都在MediaAdapter中作適配。ide

橋模式

將抽象和實現放在兩個不一樣的類層次中,使它們能夠獨立地變化。——《Head First 設計模式》
如何理解:

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();
    }
}

通常來講,直接繼承TheAbstractClass來實現func方法。在橋模式下,繼承TheAbstractClass以後,func方法的具體實現則在經過this.bridge實現的。
橋模式和適配器模式的區別能夠看這篇文章

過濾器模式

相似函數式編程中的filter

組合模式

對象中包含對象,用實現樹型結構,對單個對象和組合對象的使用具備一致性。

裝飾模式

用於動態地給一個對象添加一些額外的職責。
例:
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();    
}

經過裝飾器SpecificDecorator,能夠在原來的OriginImpl.func()的基礎上do something else

外觀模式

用於隱藏系統的複雜性,提供一致的操做界面。
例如:
1,ClassA, ClassB, ClassC三個類分別有methodA, methodB, methodC三個方法
2,建立Facade類,關聯ClassA, ClassB, ClassC,提供methodA, methodB, mehtodC
3,經過Facade就能夠調用mehtodA, methodB, methodC了

享元模式

就是共享對象,將原來建立的對象保存起來,下次須要使用的時候優先使用已經建立過的相同對象。

代理模式

爲其餘對象提供一種代理以控制對這個對象的訪問。

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爲代理類,經過Proxy來間接的調用OriginImpl.func()

責任鏈模式

將請求的發送者和請求的處理者解耦。
當有多種類型(type)的Request,每一個Request有一個指定的handler,經過把全部的handler鏈接起來造成一條鏈handlerLink。請求能夠不用發送到指定的handler,直接發送到handlerLink,鏈中的每一個handler判斷type是否是本身的要處理的,若是不是則傳遞到下一個handler

命令模式

對命令請求者(Invoker)和命令實現者(Receiver)的解耦,方便對命令進行各類控制。

ICommand: 命令接口,有execute方法
Command: 命令實現類
Invoker: 請求發送者
Receiver: 請求接收者,負責執行實際的業務邏輯

不用命令模式:
想要調用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();

命令模式實現Invoker與Receiver的隔離,Command與Receiver耦合。發送者只接收命令。當要擴展新的功能的時候,建立新的ICommand的實現類交給Invoker便可。

解釋器模式

我的理解就是,解釋器的做用就是把人能看明白的東西解釋一下,讓機器也看明白。好比,python代碼是給人看的,python解釋器就是把代碼解釋成機器能執行的指令;計算表達式(1+2+3*4/7)是人能看懂的,計算器的做用就是把計算表達式解釋成能執行的一系列的簡單運算。

代碼和計算表達式這樣的問題有幾個重要的特徵:

  • 用什麼元素來書寫,在計算表達式中就是數字(0-9)和運算符(+-*/),在代碼中就是字母、數字和符號
  • 怎麼書寫(文法),在計算表達式中運算符和數字必須交替出現,在代碼中就是各類語言和各自的語法規則。

因此,有規則可循的問題均可以用解釋器模式來解決。可是將問題的規則提煉出來是很麻煩的,並且規則很複雜的時候更加難以提煉,成本很高。所以,只有當一類問題發生的頻率足夠高的狀況下才適合用解釋器模式。

迭代器模式

爲不一樣的數據結構提供統一的順序遍歷的操做。

中介者模式

假設有ABCD四個對象,若是兩兩交互的話每一個對象要維護三條鏈路。
加入中介,每一個對象維護一條鏈路。

備忘錄模式

保存歷史狀態,以即可以恢復到原先的狀態。

觀察者模式

使用場景:一個對象A的改變要通知到一個或多個其餘對象。

加入觀察者可讓A沒必要關心具體要通知改變的其餘對象,由觀察者來發通知。

狀態模式

類的行爲是基於它的狀態改變的,容許對象在內部狀態發生改變時改變它的行爲,對象看起來好像修改了它的類。如何理解這句話?

類(TheClass), 狀態(State), 行爲(action)

代碼:

public class TheClass{
    private State state;
    
    public void action(){
        //TODO depends on state
    }
}

TODO這塊能夠用switch case或者if else來實現,State通常是一個int

typedef int State;//狀態通常是個整型

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;
        }
    }
}

不符合開閉原則,由於若是要增長一種狀態,則須要修改代碼,添加case

用狀態模式,State是一個interface, 擁有一個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()
    }
}

若是要添加一個C狀態,只須要新建一個StateC實現State接口便可。

空對象模式

對象有方法,NULL什麼都沒有。空對象目的在於提供默認的方法。這樣咱們空對象執行相關操做時也不會報錯。

策略模式

從輸入獲取輸出能夠有多種策略,例如排序問題就有插入、冒泡、快速、歸併等不一樣和策略,均可以獲得相同的結果。各類策略分別適用於特定的輸入,例如,對於自己有序數組來講,冒泡策略只須要遍歷一遍就能夠。

若是用if else來解決排序問題:

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)
}

將策略抽象成接口,不一樣的策略實現該接口。

模板模式

一個操做operate,有多個step。咱們把operate定義爲固定的模板,各個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
    }
}

訪問者模式

  • 被訪問者接口(Acceptor): 有accept(visitor)方法,接收visitor的訪問
  • 被訪元素(AcceptorItem): 實現了Acceptor接口,一般不會直接暴露給Visitor。
  • 訪問者(Visitor): 有visit(acceptor)方法,訪問acceptor元素
  • 被訪問對象(Containor): 直接暴露給Visitor出來的被訪問對象,至關於一個Containor,以必定的結構組織了各個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 Collection<Acceptor> acceptors;
    
    public void accept(Visitor visitor){
        Iteratro it = acceptors.getIterator();
        while(it.hasNext()){
            visitor.visit(it.next());
        }
    }
}

訪問者(Vistor)有多個visit方法,visit根據不一樣的Accepctor執行不一樣的邏輯。若是要擴展新的Acceptor,須要修改Visitor接口,這樣不符合開閉原則;而擴展新的Visitor時,則只須要新增Visitor實現就能夠了。所以,訪問者模式適合對象結構穩定,而常常須要擴展對象操做的場景。

MVC模式

MVC模式是一種軟件架構模式,應於交互式應用中。交互式應用就是界面+操做+數據後臺。若是不使用MVC模式,界面的代碼和對數據操做的代碼雜在一塊兒,不方便重用,也不容易維護。MVC模式分離了界面和數據,界面(View)經過控制器(Controller)提供的接口操做數據模型(Model),後臺數據變動以後經過控制器通知到相關的界面。

相關文章
相關標籤/搜索