設計模式讀書筆記

這段時間學習了一下軟件開發中的設計模式,這篇讀書筆記就談談我對設計模式的理解。java

設計模式不是一套api,而是一種可複用的、通常性的解決方式,相似於之前談過的MSF,其官方定義以下:設計模式(design pattern)是軟件開發人員在軟件開發過程當中面臨的通常問題的解決方案。設計模式的提出自己是基於面向對象的語言的,沒有了面向對象的繼承與多態,全部設計模式都玩不轉了。設計模式分爲三大類,建立型、結構型、行爲型,此次就主要談談建立型設計模式。程序員

首先是最多見的工廠模式,官方的說法是:定義一個建立對象的接口,讓其子類本身決定實例化哪個工廠類,工廠模式使其建立過程延遲到子類進行。這句話真的很難懂,因此不如舉個例子,到汽車廠提車,不管寶馬、奧迪仍是奧拓只要提就好了,沒必要管具體的製造細節。這樣的說法感受清晰了些,能夠看出工廠模式提供了必定程度上的封裝,但具體它要實現怎樣的目的呢?放一段Java源碼:設計模式

public interface Shape {
   void draw();
}

public class Rectangle implements Shape {

   @Override
   public void draw() {
      System.out.println("Inside Rectangle::draw() method.");
   }
}

public class Square implements Shape {

   @Override
   public void draw() {
      System.out.println("Inside Square::draw() method.");
   }
}

public class Circle implements Shape {

   @Override
   public void draw() {
      System.out.println("Inside Circle::draw() method.");
   }
}

public class ShapeFactory {

   public Shape getShape(String shapeType){
      if(shapeType == null){
         return null;
      }        
      if(shapeType.equalsIgnoreCase("CIRCLE")){
         return new Circle();
      } else if(shapeType.equalsIgnoreCase("RECTANGLE")){
         return new Rectangle();
      } else if(shapeType.equalsIgnoreCase("SQUARE")){
         return new Square();
      }
      return null;
   }
}

 

這樣一切都清晰了,用我本身的話說,工廠模式實現的是對一類產品族的封裝。其實你們多少都用過工廠模式,當初學習C++虛基類以及Java接口的時候,確定嘗試過經過一個抽象類實現各類相應的實體類,這個過程其實即便工廠模式的核心,即基於接口與實現技術,對於C++也能夠說是虛基類與繼承技術。要說工廠模式比咱們原來寫的東西多了什麼,就是最後的 ShapeFactory 類以及其 getShape 方法,我相信當初大部分人都不會使用這種寫法,但仔細一下這種方式實現了對上層很是乾淨的封裝,對於用戶來講不再須要想着new一個什麼樣的對象,須要的只是產生一個 ShapeFactory 對象,而後從中 getShape 獲得想要的對象,即只要走進汽車工廠就能夠取到各類各樣的車。api

有句題外話,就是我在看工廠模式的過程當中忽然模糊了Java中虛基類與接口的區別,查了查纔想起來虛基類的部分函數是已經實現了的,子類只需實現那些沒有實現的類,而接口的函數所有都是虛函數,實現類必須實現其中所有的函數。安全

 

下面看看單例模式,這種模式要求該類本身負責建立本身,且需確保只有單個對象被建立。爲了確保該類不會被實例化,有種騷操做就是把構造函數設爲 private ,這樣若是該類被 new 則編譯器報錯,這種操做真的是長見識。具體的單例模式代碼還分爲懶漢模式和餓漢模式。多線程

懶漢模式:ide

public class Singleton {  
    private static Singleton instance;  
    private Singleton (){}  
    public static synchronized Singleton getInstance() {  
    if (instance == null) {  
        instance = new Singleton();  
    }  
    return instance;  
    }  
} 

 

其中 synchronized 關鍵字是爲了保證線程安全,即多線程訪問時給對象上鎖。從下能夠看到餓漢模式不存在這種問題。函數

餓漢模式:性能

public class Singleton {  
    private static Singleton instance = new Singleton();  
    private Singleton (){}  
    public static Singleton getInstance() {  
    return instance;  
    }  

 

這二者的區別就在於,懶漢模式的初始化在被調用時進行,而餓漢模式的初始化在類加載時就進行了,這帶來的結果就是懶漢模式更節省內存,可是其自己存在線程不安全的問題,必須使用 sychronized 關鍵字,因此性能會比較低,通常在單例用的次數少且消耗資源大時使用。學習

單例模式這樣就講清楚了,可是帶來的新的問題是類到底什麼時候被初始化?我查了相關資料發現,JVM並無規定類什麼時候被加載(加載到JVM方法區和堆區),但嚴格規定了什麼時候被初始化,其中最多見的兩種狀況就是 new 一個類或者調用其靜態方法(還包括讀取、設置靜態字段等狀況),一旦出現上述狀況類就必須被初始化,而餓漢模式中的static成員instance在類加載時被賦值,同時 new 了自身,因此該類在加載時就初始化,懶漢模式就能夠等到被調用再初始化。

可見,這麼短短兩段代碼中蘊藏着那麼多知識,充分體現了第一次提出規範單例模式的程序員的智慧。

最後再談談原型模式。原型模式的目的是建立重複的對象,好比說,若是類的初始化須要不少資源,不如只保存一份相應的對象。從這個角度看,原型模式很像是單例模式的擴展,能夠當作是一個產品族的單例集合。看看以下java代碼:

public abstract class Shape implements Cloneable {
   
   private String id;
   protected String type;
   
   abstract void draw();
   
   public String getType(){
      return type;
   }
   
   public String getId() {
      return id;
   }
   
   public void setId(String id) {
      this.id = id;
   }
   
   public Object clone() {
      Object clone = null;
      try {
         clone = super.clone();
      } catch (CloneNotSupportedException e) {
         e.printStackTrace();
      }
      return clone;
   }
}

public class ShapeCache {
    
   private static Hashtable<String, Shape> shapeMap 
      = new Hashtable<String, Shape>();

   public static Shape getShape(String shapeId) {
      Shape cachedShape = shapeMap.get(shapeId);
      return (Shape) cachedShape.clone();
   }

   public static void loadCache() {
      Circle circle = new Circle();
      circle.setId("1");
      shapeMap.put(circle.getId(),circle);

      Square square = new Square();
      square.setId("2");
      shapeMap.put(square.getId(),square);

      Rectangle rectangle = new Rectangle();
      rectangle.setId("3");
      shapeMap.put(rectangle.getId(),rectangle);
   }
}

 

java中自帶的 Cloneable 類能夠很好地實現原型模式的目的。雖然上述代碼有些工廠模式的感受,但其實原型模式的目的與工廠模式徹底不一樣。可是,原型模式最大的用處之一就是和工廠模式結合,若是把上述代碼中的形狀改成工廠,具體的形狀改成不一樣的工廠,那麼最後的 Cache 提供的就是不一樣工廠的克隆,這很好地實現了工廠的單例性。

 

本文描述了工廠模式、單例模式、原型模式三種常見的建立型設計模式,下次再來講說結構型設計模式。

相關文章
相關標籤/搜索