設計模式總結 之 創建型1. 單例模式 SingleTon
public class Singleton { private Singleton() {} private static Singleton single=null; //靜態工廠方法 public static Singleton getInstance() { if (single == null) { single = new Singleton(); } return single; } }
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
/** * 皮膚工廠特質 */ 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
並且完成組裝的過程.構建模式主要用來針對複雜產品生產,分離部件構建細節,以達到良好的伸縮性。
把構造對象實例的邏輯移到了類的外部,在這個類外部定義了這個類的構造邏輯
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
原型模式多用於創建複雜的或者耗時的實例, 因爲這種情況下,複製一個已經存在的實例可以使程序運行更高效,或者創建值相等,只是命名不一樣的同類數據.
原型模式中的拷貝分爲"淺拷貝"和"深拷貝":
淺拷貝: 對值類型的成員變量進行值的複製,對引用類型的成員變量只複製引用,不復制引用的對象.
深拷貝: 對值類型的成員變量進行值的複製,對引用類型的成員變量也進行引用對象的複製.
/**
* 樣例類:週報
*/
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))
}