1. 程式人生 > >java常用設計模式總結

java常用設計模式總結

掌握常用的幾種(最起碼單例模式、工廠模式),瞭解其他的設計模式即可,做到手裡有糧,心裡不慌。首先,掌握每種模式的定義及使用場景。其次,掌握一個形象的例子,簡單的過一遍程式碼。
學習設計模式的真正目的:程式設計時,有意識地面向介面程式設計,多用封裝、繼承、組合、多型等OOP思想,而不僅僅是死記幾類設計模式。

常用的設計模式分類:
建立型(建立一個物件):單例模式、工廠模式、抽象工廠模式
結構型(將幾個物件組織成一個結構):橋接模式、外觀模式、代理模式
行為型(多個物件間的通訊):觀察者模式、策略模式
其中,工廠模式、橋接模式、策略模式有點像,放在一起理解(幾個物件具有共同特徵,因此繼承共同的介面,然後通過工廠、橋去訪問

)。另外,工廠模式和外觀模式(幾個物件間有先後關係,是序列的,而非工廠模式中的並行,因此幾個物件組合成一個外觀類,通過這個外觀類來訪問)區別很明顯,也因此放在一起理解。

參考引用:

設計模式定義

被反覆使用的,程式碼設計經驗的總結。

設計模式的原則

總結起來,就是多用介面/抽象類,從而增加程式碼的可擴充套件性(減少修改程式碼)。降低模組間的依賴和聯絡。
體現了OOP的模組化、可擴充套件性等特徵。

工廠模式

定義與使用場合:現在需要建立幾個物件,且這幾個物件有共同特徵,則不需要具體建立各個物件,而是建立物件工廠類即可。
一般常用靜態工廠模式。
例子:傳送郵件和簡訊(共同特徵:傳送的訊息)
這裡寫圖片描述

public interface Sender {  
    public void Send();  
}  
public class MailSender implements Sender {  
    @Override  
    public void Send() {  
        System.out.println("this is mailsender!");  
    }  
}  
public class SmsSender implements Sender {  

    @Override  
    public void Send
() { System.out.println("this is sms sender!"); } }
public class SendFactory {  

    public static Sender produceMail(){  
        return new MailSender();  
    }  

    public static Sender produceSms(){  
        return new SmsSender();  
    }  
}  
public class FactoryTest {  

    public static void main(String[] args) {      
        Sender sender = SendFactory.produceMail();  
        sender.Send();  
    }  
}  

抽象工廠模式

工廠方法模式有一個問題就是,類的建立依賴工廠類,也就是說,如果想要拓展程式,必須對工廠類進行修改,這違背了閉包原則
定義與使用場景:同上。
例子:同上。
這裡寫圖片描述

public interface Provider {  
    public Sender produce();  
}  
public class SendMailFactory implements Provider {  

    @Override  
    public Sender produce(){  
        return new MailSender();  
    }  
}  
public class SendSmsFactory implements Provider{  

    @Override  
    public Sender produce() {  
        return new SmsSender();  
    }  
}  
public class Test {  

    public static void main(String[] args) {  
        Provider provider = new SendMailFactory();  
        Sender sender = provider.produce();  
        sender.Send();  
    }  
}  

總結:如果要新增傳送微信,則只需做一個實現類,實現Sender介面,同時做一個工廠類,實現Provider介面,就OK了,無需去改動現成的程式碼。這樣做,拓展性較好!
所有工廠模式中,抽象工廠模式最先進。

策略模式及與工廠模式的區別

定義與使用場合:一個系統需要動態地在幾種類似的演算法中選擇一種。
與工廠模式異同:例項化一個物件的位置不同。對工廠模式而言,例項化物件是放在了工廠類裡面。而策略模式例項化物件的操作在呼叫的地方。本質都是繼承與多型。
例子: 現有 加/減/乘 幾種演算法,輸入引數返回值都一樣(可以理解成類似的演算法)。現在需要在呼叫時動態配置演算法策略,實現對不同演算法的呼叫。
這裡寫圖片描述

public interface Strategy {
   public int doOperation(int num1, int num2);
}
public class OperationAdd implements Strategy{
   @Override
   public int doOperation(int num1, int num2) {
      return num1 + num2;
   }
}
public class OperationSubstract implements Strategy{
   @Override
   public int doOperation(int num1, int num2) {
      return num1 - num2;
   }
}
public class OperationMultiply implements Strategy{
   @Override
   public int doOperation(int num1, int num2) {
      return num1 * num2;
   }
}
public class Context {
   private Strategy strategy;

   public Context(Strategy strategy){
      this.strategy = strategy;
   }

   public int executeStrategy(int num1, int num2){
      return strategy.doOperation(num1, num2);
   }
}
public class StrategyPatternDemo {
   public static void main(String[] args) {
       //例項化物件的位置在呼叫處
      Context context = new Context(new OperationAdd());        
      System.out.println("10 + 5 = " + context.executeStrategy(10, 5));

      context = new Context(new OperationSubstract());        
      System.out.println("10 - 5 = " + context.executeStrategy(10, 5));

      context = new Context(new OperationMultiply());        
      System.out.println("10 * 5 = " + context.executeStrategy(10, 5));
   }
}

單例模式

定義及使用場合:只有一個物件被建立。
例子:
建議採用 餓漢式 建立方法。執行緒安全,容易實現。初始化慢一點。

public class SingleObject {

   //建立 SingleObject 的一個物件
   private static SingleObject instance = new SingleObject();

   //讓建構函式為 private,這樣該類就不會被例項化
   private SingleObject(){}

   //獲取唯一可用的物件
   public static SingleObject getInstance(){
      return instance;
   }

}

觀察者模式

定義與使用場景:一個物件(subject)被其他多個物件(observer)所依賴。則當一個物件變化時,發出通知,其它依賴該物件的物件都會收到通知,並且隨著變化。
比如 聲音報警器和閃光燈報警器分別訂閱熱水器溫度,熱水器溫度過高時,發出通知,兩個報警器分別發聲、閃光以實現報警。
又比如很多人訂閱微信公眾號,該公眾號有更新文章時,自動通知每個訂閱的使用者。
**實現:**1,多個觀察者要訂閱這個物件 2,這個物件要發出通知

例子:
這裡寫圖片描述

public interface Observer {  
    public void update();  
}  
public class Observer1 implements Observer {  

    @Override  
    public void update() {  
        System.out.println("observer1 has received!");  
    }  
}  
public class Observer2 implements Observer {  

    @Override  
    public void update() {  
        System.out.println("observer2 has received!");  
    }  

}  
public interface Subject {  

    /*增加觀察者*/  
    public void add(Observer observer);  

    /*刪除觀察者*/  
    public void del(Observer observer);  

    /*通知所有的觀察者*/  
    public void notifyObservers();  

    /*自身的操作*/  
    public void operation();  
}  
public abstract class AbstractSubject implements Subject {  

    private Vector<Observer> vector = new Vector<Observer>();  
    @Override  
    public void add(Observer observer) {  
        vector.add(observer);  
    }  

    @Override  
    public void del(Observer observer) {  
        vector.remove(observer);  
    }  

    @Override  
    public void notifyObservers() {  
        Enumeration<Observer> enumo = vector.elements();  
        while(enumo.hasMoreElements()){  
            enumo.nextElement().update();  
        }  
    }  
public class MySubject extends AbstractSubject {  

    @Override  
    public void operation() {  
        System.out.println("update self!");  
        notifyObservers();  
    }  

}  
public class ObserverTest {  

    public static void main(String[] args) {  
        Subject sub = new MySubject();  
        sub.add(new Observer1());  //訂閱這個物件
        sub.add(new Observer2());  

        sub.operation();  //發出改變的一個通知
    }  

}  

代理模式

定義與使用場景:一個代理類代表一個真實類的功能,通過訪問代理類來實現對真實類的訪問。
比如買火車票這件小事:黃牛相當於是火車站的代理,我們可以通過黃牛買票,但只能去火車站進行改簽和退票。
又比如需要對原有的方法進行修改,就是採用一個代理類呼叫原有的方法,以避免修改原有程式碼。
例子:
這裡寫圖片描述
一個真實物件realSubject提供一個代理物件proxy。通過proxy可以呼叫realSubject的部分功能*,並新增一些額外的業務處理*,同時可以遮蔽realSubject中未開放的介面。
1、RealSubject 是委託類,Proxy 是代理類;
2、Subject 是委託類和代理類的介面;
3、request() 是委託類和代理類的共同方法;

interface Subject {
    void request();
}

class RealSubject implements Subject {
    public void request(){
        System.out.println("RealSubject");
    }
}

class Proxy implements Subject {
    private Subject subject;

    public Proxy(Subject subject){
        this.subject = subject;
    }
    public void request(){
        System.out.println("begin");
        subject.request();
        System.out.println("end");
    }
}

public class ProxyTest {
    public static void main(String args[]) {
        RealSubject subject = new RealSubject();
        Proxy p = new Proxy(subject);
        p.request();
    }
}

橋接模式及與策略模式的區別

定義與使用場景:訪問多種資料庫驅動(多個具有共同特徵的資料庫驅動),不是直接訪問,而是通過DriverManager橋來訪問。

這裡寫圖片描述
例子: 不再具體實現了。
這裡寫圖片描述
與策略模式的區別:(個人覺得較複雜,瞭解即可。本質都是面向介面程式設計,體現繼承與多型)
策略模式:我要畫圓,要實心圓,我可以用solidPen來配置,畫虛線圓可以用dashedPen來配置。這是strategy模式。
橋接模式:同樣是畫圓,我是在windows下來畫實心圓,就用windowPen+solidPen來配置,在unix下畫實心圓就用unixPen+solidPen來配置。如果要再windows下畫虛線圓,就用windowsPen+dashedPen來配置,要在unix下畫虛線圓,就用unixPen+dashedPen來配置。
所以相對策略模式,橋接模式要表達的內容要更多,結構也更加複雜。

外觀模式

定義與使用場景:見例子。又比如,去醫院看病,可能要去掛號、門診、劃價、取藥,讓患者或患者家屬覺得很複雜,如果有提供接待人員,只讓接待人員來處理,就很方便。
例子:計算機啟動,需要先啟動CPU,再啟動memory,最後啟動disk。這三個類之間具有先後關係(依賴關係)。
這裡寫圖片描述
與工廠模式的區別:工程模式多個類具有共同特徵(繼承一個共同的介面),是並列的。而外觀模式多個類是有先後關係,是序列的,用組合。

貼部分程式碼:

public class Computer {  
//是組合,而非繼承。這是與工程模式的顯著區別。
    private CPU cpu;  
    private Memory memory;  
    private Disk disk;  

    public Computer(){  
        cpu = new CPU();  
        memory = new Memory();  
        disk = new Disk();  
    }  

    public void startup(){  
        System.out.println("start the computer!");  
        cpu.startup();  
        memory.startup();  
        disk.startup();  
        System.out.println("start computer finished!");  
    }  

    public void shutdown(){  
        System.out.println("begin to close the computer!");  
        cpu.shutdown();  
        memory.shutdown();  
        disk.shutdown();  
        System.out.println("computer closed!");  
    }  
}  
public class User {  

    public static void main(String[] args) {  
        Computer computer = new Computer();  
        //將計算機的啟動過程封裝成一個類
        computer.startup();  
        computer.shutdown();  
    }  
}  

生產者-消費者模式

定義與使用場景:生產者把資料放入緩衝區,而消費者從緩衝區取出資料。
例子:緩衝區一般為佇列(FIFO),但在生產消費較為頻繁時,佇列push,pop記憶體消耗較大,此時可以考慮環形緩衝區(以陣列、連結串列方式實現)。
通過互斥鎖防止緩衝區同時讀寫。通過訊號量控制緩衝區大小(滿的時候不允許寫,空的時候不允許讀)

相關推薦

java常用設計模式總結

掌握常用的幾種(最起碼單例模式、工廠模式),瞭解其他的設計模式即可,做到手裡有糧,心裡不慌。首先,掌握每種模式的定義及使用場景。其次,掌握一個形象的例子,簡單的過一遍程式碼。 學習設計模式的真正目的:程式設計時,有意識地面向介面程式設計,多用封裝、繼承、組合、

JAVA常用設計模式

ipp targe aec atd jmh 設計模式 模式 java left 巴揭殼景枚嫡倚濫煽吠徑http://www.docin.com/vxuo069 蔚贍卣碩狼吠亢照某嶽魏徹http://www.docin.com/idj90593 黃濁偃由友兔兆凍寺敬踴酌沮持h

Java常用設計模式——觀察者模式

ray stat param servers face oid println override 角色 觀察者模式又叫做發布-訂閱-模式、模型-視圖-模式、源-監聽器-模式或者從屬者模式。觀察者模式定義了一種一對多的依賴關系,讓多個觀察者對象同時監聽某一個主題對

Java常用設計模式——策略模式

nts static 管理 選擇 span disco rri contex 由於 策略模式定義了一系列的算法,並將每一個算法封裝起來,而且使它們還可以相互替換,策略模式讓算法獨立於使用它的客戶而獨立變化。策略模式使這些算法在客戶端調用它們的時候能夠互不影響地變化

java常用設計模式--觀察者模式簡單例子

package com.ruanyun;import java.util.List;import java.util.Vector;/** * @Auther: maxw * @Date: 2018/11/10 16:14 * @Description:觀察者模式 * 基本概念: * 觀察者模式屬於行為型模式

java常用設計模式--單例模式簡單例子

package com.ruanyun;/** * @Auther: maxw * @Date: 2018/11/10 17:29 * @Description: */public class Test4 { public static void main(String args[]){

java常用設計模式--工廠方法模式簡單例子

package com.ruanyun;/** * @Auther: maxw * @Date: 2018/11/12 11:02 * @Description:工廠方法模式:有四個角色,抽象工廠模式,具體工廠模式,抽象產品模式,具體產品模式。不再是由一個工廠類去例項化具體的產品,而是由抽象工廠的子類去例項化

java常用設計模式--抽象工廠模式簡單例子

package com.ruanyun;/** * @Auther: maxw * @Date: 2018/11/12 11:23 * @Description:抽象工廠模式:與工廠方法模式不同的是,工廠方法模式中的工廠只生產單一的產品,而抽象工廠模式中的工廠生產多個產品。 * 還有個抽象工廠方法模式 只需要

java常用設計模式--享元模式簡單例項

package com.ruanyun;import java.util.HashMap;import java.util.Map;/** * @Auther: maxw * @Date: 2018/11/21 09:47 * @Description:享元模式:“享”就是分享之意,指一物被眾人共享,而這也正

java常用設計模式連結

轉自:作者:dreamOwn     https://www.cnblogs.com/wabi87547568/p/5280905.html   Java中常用的設計模式 1.單例模式   單例模式有以下特點:  1、單例類只能有一個例項。  2、單例類必須自己

常用設計模式總結(面試常問)

Singleton(單例模式) 一句話總結:一個類在Java虛擬機器中只有一個物件,並提供一個全域性訪問點。 生活中例子:太陽、月亮、國家主席等。 解決什麼問題:物件的唯一性,效能浪費太多。 專案裡面怎麼用:資料庫連線物件,屬性配置檔案的讀取物件。 模式結構:分為餓漢式和懶漢式(

Java常用設計模式————觀察者模式

引言 作為設計模式中常用的行為型模式,其主要解決的是一個複合物件(或組合物件)的基礎依賴物件的通知問題。 簡單的說,當一個複合物件依賴多個其他物件時,我們稱這種關係為一對多的關係。當這個複合物件狀態發生了改變,其他組成它的物件都可以收到來自複合物件的通知。 依賴物件中存在一個指向複合

java常用設計模式10—裝飾模式

我的設計模式學習系列專案地址: GitHub - GodisGod/DesignPatternStudy: 設計模式學習demo https://github.com/GodisGod/DesignPatternStudy 介紹: 裝飾模式也稱為包裝模式,結構型設計

java常用設計模式9——代理模式

介紹:代理模式也稱為委託模式。 定義:為其它物件提供一種代理以控制對這個物件的訪問。 程式碼舉例: 山中有一個大王,大王有一個嘍囉,大王需要巡山來保證自己的地盤不被入侵,但是大王怎麼能自己去巡山呢?所以就要嘍囉代替大王來巡山。 我們用代理模式描述這個場景 //任務 publi

java常用設計模式8——模板方法模式

這個設計模式應該是最簡單的設計模式,因為大家平時都在使用,可能只是不知道它還是個設計模式吧 相關程式碼下載: GitHub - GodisGod/DesignPatternStudy: 設計模式學習demo https://github.com/GodisGod/Desi

java常用設計模式7——責任鏈模式

嘿嘿,這次介紹一個好玩的設計模式 — — 責任鏈模式 相關程式碼下載: GitHub - GodisGod/DesignPatternStudy: 設計模式學習demo https://github.com/GodisGod/DesignPatternStudy

java常用設計模式6——狀態模式

狀態模式介紹: 1、狀態模式中的行為是由狀態來決定的,不同的狀態下有不同的行為。 2、狀態模式和策略模式的結構幾乎完全一樣,但它們的目的、本質卻完全不一樣。狀態模式的行為是平行的,不可替換的,策略模式的行為是彼此獨立,可相互替換的。 3、狀態模式把物件的行為包裝在不同的狀態物件裡,每一個

java常用設計模式5——策略模式

通常一個問題有多個解決方案的時候,我們會把每個解決方案封裝到自己的類裡面,這樣可以避免在同一個類裡通過if,else或者switch來判斷使用哪種方案。 比如: if(type == 1){ return fun1(); }else if(type == 2){ return f

java常用設計模式4——觀察者模式

當被觀察者的狀態傳送改變的時候,所有觀察它的物件都會得到通知並自動更新。 觀察者模式UML圖: Subject: 抽象主題。把所有觀察者物件的引用儲存在一個集合裡,每個主題都可以有任意數量的觀察者,抽象主題提供一個介面,可以增加和刪除物件。 ConcreteSubject:具體主題

java常用設計模式3——工廠方法模式

1、工廠方法模式定義:定義一個用於建立物件的介面,讓子類決定例項化哪個類 2、工廠方法模式的使用場景:在任何需要生成複雜物件的地方,都可以使用工廠方法模式。複雜物件適合使用工廠模式,用new就可以完成建立的物件無需使用工廠模式 多工廠方法模式 程式碼示例: 1、定義一個抽象的產品