设计模式总结 之 创建型
参考:
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))
}