設計模式總結 之 創建型

設計模式總結 之 創建型
參考:
http://blog.csdn.net/jason0539
設計模式和原則 強烈推薦 http://blog.csdn.net/zhengzhb/article/category/926691
總共有24中設計模式,分爲3類:
 創建型模式,共種:單例模式簡單工廠、抽象工廠模式、工廠方法模式、建造者模式、原型模式。
結構型模式,共七種:適配器模式、裝飾器模式、代理模式、外觀模式、橋接模式、組合模式、享元模式。
行爲型模式,共十一種:策略模式、模板方法模式、觀察者模式、迭代子模式、責任鏈模式、命令模式、備忘錄模式、狀態模式、訪問者模式、中介者模式、解釋器模式。

1. 單例模式  SingleTon

結構解析:
java中 單例類中私有化構造函數和實例化對象    防止創建新實例和直接訪問實例   飯後提供訪問實例的方法
scala中直接object即可
public class Singleton {  
    private Singleton() {}  
    private static Singleton single=null;  
    //靜態工廠方法   
    public static Singleton getInstance() {  
         if (single == null) {    
             single = new Singleton();  
         }    
        return single;  
    }  
}  

最簡單的模式,單列類只有一個實例,類中靜態實現,對外提供訪問該例的方法
scala中實現只需要 一個Object就可以實現單例模式
object LoadBalance {
  //服務器組
  val servers = new ArrayBuffer[String]()

  /**
   * 增加服務器
   * @param server 服務器名
   */

  def addServer(server: String) {
    println(s"add server :$server")
    servers += server
  }

  /**
   * 刪除服務器
   * @param server 服務器名
   */
  def removeServer(server: String) {
    println(s"remove server : $server")
    servers -= server
  }

  /**
   * 隨機獲取服務器轉發
   * @return 服務器名
   */

  def getServers(): String = {
    servers(Random.nextInt(servers.length))
  }
}

/**
 * 單例測試客戶端
 */
object Client extends App {

  Console.println("singleTon Client Test")
  // 構建負載均衡器1
  val balance1 = LoadBalance
  // 構建負載均衡器2
  val balance2 = LoadBalance

  //判斷兩個balance是否一致

  println(s"兩個均衡器是否一致 :  ${balance1.eq(balance2)}")

  //添加服務器
  balance1.addServer("server1")
  balance1.addServer("server2")
  balance1.addServer("server3")
  balance1.addServer("server4")

  //隨機獲取服務器

  for (i <- 1 to 10) {
    println(s"get server : ${balance1.getServers()}")
  }

  //使用balance2刪除 服務器

  balance2.removeServer("server1")

  //隨機獲取服務器

  for (i <- 1 to 10) {
    println(s"get server : ${balance1.getServers()}")
  }

}


2. 簡單工廠 SimpleFactory

結構解析:
抽象類產品 
具體類產品
工廠  :根據輸入參數選擇返回具體的產品

簡單工廠模式,根據外界給定的原料,在加上自身封裝好的判斷,生產出不同類型的相應的產品、對象。

簡單工廠模式使用場景:工廠類負責創建的對象比較少;客戶只知道傳入工廠類的參數,對於如何創建對象(邏輯)不關心

abstract  class Chart {
    def display():Unit
}

/**
 * 柱狀圖,繼承抽象圖
 */
class  HistogramChart extends  Chart{
    println("初始化柱狀圖")

    /**
     * 展示方法
     */
    override def display(): Unit = {
        println("顯示柱狀圖")
    }
}

/**
 * 餅狀圖,繼承抽象圖
 */
class  PieChart extends  Chart{
    println("初始化餅狀圖")

    /**
     * 展示方法
     */
    override def display(): Unit = {
        println("顯示餅狀圖")
    }
}


/**
 * 折線圖,繼承抽象圖
 */
class LineChart extends  Chart{
    println("初始化折線圖")

    /**
     * 展示方法
     */
    override def display(): Unit = {
        println("顯示折線圖")
    }
}


/**
 * 工廠方法,用於產出具體產品
 */
object  Chart {
    /**
     * 通過模式匹配更加優雅實現
     * @param style 產品類型
     * @return 具體產品
     */
    def apply(style:String) = style match {
        case "histogram" => println("創建柱狀圖");new HistogramChart
        case "pie" => println("創建餅狀圖");new PieChart
        case "line" =>println("創建折線圖"); new LineChart
    }
}


/**
 * Created by ctao on 2015/8/6.
 * 測試客戶端
 */
object Client2 extends  App{
    //產出餅狀圖
    val pie = Chart("pie")
    pie.display()
    //產出柱狀圖
    val histogram = Chart("histogram")
    histogram.display()
    //產出折線圖
    val line = Chart("line")
    line.display()

}

3. 抽象工廠 AbstractFactory

結構解析:
抽象工廠:接口
具體工廠:object
抽象產品:接口
具體產品:具體工廠中的內部類
抽象工廠是應對產品族概念的。比如說,每個汽車公司可能要同時生產轎車,貨車,客車,那麼每一個工廠都要有創建轎車,貨車和客車的方法。
/**
 * 皮膚工廠特質
 */

trait SkinFactory {
  
  def createButton():Button
  def createTextField():TextField
  
}

/**
 * 按鈕特質
 */
trait Button{
  def display():Unit
}

/**
*文本框特質
*/

trait   TextField{
  def display():Unit
}

/**
* 春天皮膚工廠
*/

object SpringSkinFactory extends SkinFactory{
  
  class SpringButton extends Button{
    override def display():Unit=println("Spring Button")
  }
  
  class SpringTextField extends TextField {
    override def display():Unit=println("Spring TextField ")
  }
  
  override def createButton():Button=new SpringButton
  
  override def createTextField():TextField =new SpringTextField
}

/**
* 夏天皮膚工廠
*/

object SummerSkinFactory extends SkinFactory{
  
  class SummerButton extends Button{
    override def display():Unit=println("Summer Button")
  }
  
  class SummerTextField extends TextField {
    override def display():Unit=println("Summer TextField ")
  }
  
  override def createButton():Button=new SummerButton
  
  override def createTextField():TextField =new SummerTextField
}



/**
*客戶端測試
* 
*/

object Client3 extends App{
  /**
   * 創建皮膚工廠
   */
  val factory :SkinFactory =  SpringSkinFactory
  
  factory.createButton().display()
  factory.createTextField().display()
}

4.工廠模式 Factory

簡單工廠模式的工廠類一般是使用靜態方法,通過接收的參數的不同來返回不同的對象實例

工廠方法是針對每一種產品提供一個工廠類。通過不同的工廠實例來創建不同的產品實例。

抽象工廠是應對產品族概念的。比如說,每個汽車公司可能要同時生產轎車,貨車,客車,那麼每一個工廠都要有創建轎車,貨車和客車的方法。

結構解析:
工廠接口:Factory
具體工廠:object 每個工廠返回自己的產品 DatabaseLoggerFactory
產品接口:Logger
具體產品:DataBaseLogger FilLogger

工廠方法是針對每一種產品提供一個工廠類。通過不同的工廠實例來創建不同的產品實例。在同一等級結構中,支持增加任意產品

trait Factory {
  def createLogger():Logger
}

trait Logger {
  def writeLog():Unit
}

class DatabaseLogger extends Logger{
  override def writeLog(): Unit=println("數據庫日誌記錄")
}

class FileLogger extends Logger{
  override def writeLog():Unit = println("文件日誌記錄")
}

object DatabaseLoggerFactory extends Factory{
  override def createLogger(): Logger = new DatabaseLogger
}

object FileLoggerFactory extends Factory{
  override def createLogger():Logger = new FileLogger
}


/**
*測試客戶端
*/

object Client4 extends App{
  
  val logger1:Factory = DatabaseLoggerFactory 
  val logger2:Factory = FileLoggerFactory
  logger1.createLogger().writeLog()
  logger2.createLogger().writeLog()
}


5.建造者模式  Builder

結構解析:四要素
1.產品類   Actor
2.抽象創建者 ActorBuilder
3.創建者   HeroBuilder  DevilBuilder 
4.導演類  
創建者模式是創建型模式中最負責的一個設計模式了,創建者負責構建一個對象的各個部分,
並且完成組裝的過程.構建模式主要用來針對複雜產品生產,分離部件構建細節,以達到良好的伸縮性。
把構造對象實例的邏輯移到了類的外部,在這個類外部定義了這個類的構造邏輯

trait ActorBuilder {
  protected var actor: Actor

  def buildRole(): Unit
  def buildSex(): Unit
  def buildFace(): Unit
  def buildCostume(): Unit
  val BareHead = false
  def buildHairStye(): Unit

  def creatActor(): Actor

  /*
   * 控制樞紐,控制每一步的順序
   */
  def construct(ab: ActorBuilder): Actor = {
    //先設置角色,再設置性別,其次是臉型,服裝,用鉤子程序判斷是否是光頭,不是光頭則設置髮型
    ab.buildRole()
    ab.buildSex()
    ab.buildFace()
    ab.buildCostume()
    if (!ab.BareHead) {
      ab.buildHairStye()
    }
    ab.creatActor()
  }
}

class Actor {
  var role: String = _
  var sex: String = _
  var face: String = _
  var costume: String = _
  var hairStye: String = "光頭"
}

object HeroBuilder extends ActorBuilder {

  override protected var actor: Actor = new Actor()

  override def buildRole() = actor.role = "英雄"

  override def buildSex() = actor.sex = "男"

  override def buildFace() = actor.face = "英俊"

  override def buildCostume() = actor.costume = "盔甲"

  override def buildHairStye() = actor.hairStye = "飄逸"

  override def creatActor() = actor
}

object DevilBuilder extends ActorBuilder {
  override protected var actor: Actor = new Actor()

  override def buildRole() = actor.role = "惡魔"

  override def buildSex() = actor.sex = "妖"

  override def buildFace() = actor.face = "醜陋"

  override def buildCostume() = actor.costume = "黑衣"

  override def buildHairStye() = actor.hairStye = "我想要頭髮"

  /**
   * 由於鉤子程序的存在並不會執行buildHairStyle
   */
  override val BareHead = true
  override def creatActor() = actor
}

/**
 * 測試客戶端
 */

object Client5 extends App {
  val ab1: ActorBuilder = HeroBuilder
  val actor1 = ab1.construct(ab1)
  println(actor1.sex)

  val ab2: ActorBuilder = DevilBuilder
  val actor2 = ab2.construct(ab2)
  println(actor2.sex)
}


6.原型模式 prototype

結構解析:
原型類
原型實現類  java中是重寫clone函數讓類課被複制
原型模式是一種創建型設計模式,它通過複製一個已經存在的實例來返回新的實例,而不是新建實例.被複制的實例就是我們所稱的原型,這個原型是可定製的.
原型模式多用於創建複雜的或者耗時的實例, 因爲這種情況下,複製一個已經存在的實例可以使程序運行更高效,或者創建值相等,只是命名不一樣的同類數據.

原型模式中的拷貝分爲"淺拷貝"和"深拷貝":
淺拷貝: 對值類型的成員變量進行值的複製,對引用類型的成員變量只複製引用,不復制引用的對象.
深拷貝: 對值類型的成員變量進行值的複製,對引用類型的成員變量也進行引用對象的複製.
/**
 * 樣例類:週報
 */
case class WeeklyLog(var name: String, var date: String, var context: String, var attachment: Attachment)

/**
 * 附件類樣例
 */

case class Attachment(var name: String) {
  def download() = println(s"下載附件,附件名爲:$name")
}

//object Client6 extends App { //不使用原型
//  var log_previous = new WeeklyLog("王穎", "週六", "報告內容", new Attachment("報告.ppt"))
//  val log_new = log_previous.copy()
//  /**
//   * 結果爲false,由此可以看出爲深克隆
//   *   Java支持我們對一個對象進行克隆,通常用在裝飾模式和原型模式中。那麼什麼是深克隆,什麼是淺克隆呢。
//   *
//   *   【淺克隆】,通常只是對克隆的實例進行復制,但裏面的其他子對象,都是共用的。
//   *
//   *   【深克隆】,克隆的時候會複製它的子對象的引用,裏面所有的變量和子對象都是又額外拷貝了一份。
//   */
//  println(log_new.eq(log_previous))
//
//  /**
//   * 結果爲true,附件對象爲淺克隆
//   */
//  println(log_new.attachment.eq(log_previous.attachment))
//}

/**
 * 原型管理器
 */

//*************以下爲使用原型

case class OfficeDocument(title: String) {
  def display(): Unit = { println(s"公文標題爲:$title") }
}

/**
 * 可行性分析報告
 */

class FAR(title: String) extends OfficeDocument(title)

/**
 * 軟件需求規格書
 */
class SRS(title: String) extends OfficeDocument(title)

object PrototypeManager {
  //存儲officedocument對象
  var ht = new scala.collection.mutable.HashMap[String, OfficeDocument]

  ht += ("far" -> new FAR("<可行性報告>"))
  ht += ("srs" -> new SRS("<軟件規格需求說明書>"))

  //增加文章模板
  def addOfficeDucoment(key: String, officeDocument: OfficeDocument) = ht += (key -> officeDocument)

  //獲取模板

  def getOfficeDocument(key: String): OfficeDocument = ht.getOrElse(key, new OfficeDocument("null")).copy()

}

/**
 * 測試客戶端
 */
object Client6 extends App {
  //原型管理器

  val pr = PrototypeManager
  //公文對象  從hashmap中獲取克隆對象
  val doc1 = pr.getOfficeDocument("")
  val doc2 = pr.getOfficeDocument("")

  doc1.display()
  doc2.display()

  println(doc1.equals(doc2))
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章