Scala设计模式UML图例和代码实现实战 结构模式--(flyweight)享元模式

16 篇文章 0 订阅
16 篇文章 2 订阅

Scala设计模式UML图例和代码实现实战 结构模式--(flyweight)享元模式

示例类图对于类图,首先让我们假设我们正在尝试表示类似于以下的色盲测试的绘图:正如我们所看到的,它由不同大小和颜色的圆组成。

潜在地,这可能是无限大的图片,它可以有任意数量的圆圈。为了简单起见,让我们设置一个限制,我们只能有五种不同的圆形颜色 - 红色,绿色,蓝色,黄色和洋红色。

以下是我们的类图表示使用享元(flyweight)设计模式表示前一个图像的图像:实际的享元(flyweight)设计模式是通过CircleFactory,Circle和Client类实现的。客户端请求工厂并返回Circle的新实例,或者如果存在具有所需参数的实例,则从缓存返回它。对于此示例,共享数据将是具有其颜色的Circle对象,然后每个特定圆将具有其自己的位置和半径。图形将包含包含所有信息的实际圆圈。使用我们的代码示例(前面的图表所基于的代码示例)将会更加清晰。

代码示例现在是时候看看在Scala代码中表达时flyweight设计模式的样子。我们将使用前面显示的相同示例。值得注意的是,在代码版本中,某些类具有与图中不同的名称。其原因是Scala命名约定。我们将明确指出在执行代码时发生这种情况的位置。

关于(flyweight)享元设计模式和我们的例子的一个有趣的事情是它实际上使用了我们之前已经经历过的其他设计模式和技术。我们还会在查看代码时指出它们。

我们做的第一件事就是代表颜色。这与实际的flyweight设计模式无关,但我们决定使用ADT(抽象数据类型):如果我们运行此代码,我们将得到以下输出:在更早地定义Circle类时,我们向构造添加了一条打印消息。从上图中,我们可以看到每个圆圈仅使用特定颜色创建一次,即使我们要求更多次来构建我们的图形。最后一行显示我们有五个不同的圆形对象,即使我们的图形包含10个不同的圆圈。

这只是一个例子来说明flyweight的工作原理。在现实生活中,flyweight对象将共享更多属性,从而降低整个应用程序的总体内存占用量。

它有什么好处正如我们之前提到的,当我们试图降低应用程序使用的内存时,flyweight享元设计模式很有用。使用共享对象,我们的应用程序将需要较少的构造和对象的破坏,这可以进一步提高性能。

flyweight享元模式有哪些缺点呢?   

1.根据共享数据的数量,有时不同的共享对象的数量可能会急剧增长,而不会带来太多的好处。而且,它可能使工厂及其使用复杂化。

2.多线程应用程序在与工厂合作时需要格外小心。最后但同样重要的是,开发人员在使用共享对象时需要非常小心,因为它们中的任何更改都可能影响整个应用程序。幸运的是,在Scala中,由于不变性,这不是一个问题。

 

sealed abstract class Color

case object Red extends Color

case object Green extends Color

case object Blue extends Color

case object Yellow extends Color

case object Magenta extends Color

在我们定义了颜色后,我们可以实现我们的Circle类:

class Circle(color: Color) {

System.out.println(s"Creating a circle with $color color.")

override def toString(): String = s"Circle($color)"

}

圆圈将是flyweight对象,因此模型仅包含将与其他圆形实例共享的数据。 现在我们有了圈子的模型,我们可以创建我们的CircleFactory。 顾名思义,它使用工厂设计模式。 这是它的代码:

import scala.collection.mutable.Map

object Circle {

val cache = Map.empty[Color, Circle]

def apply(color: Color): Circle = cache.getOrElseUpdate(color,

new Circle(color))

def circlesCreated(): Int = cache.size

}

我们有一个伴随对象,用于在Scala中实现工厂设计模式。 这就是为什么这里的名称与前面显示的图表不同的原因。 此表示允许我们使用以下语法获取圆的旧实例或创建新实例:

Circle(Green)

现在我们有了circle和factory,我们可以实现Graphic类:

import scala.collection.mutable.ListBuffer

class Graphic {

val items = ListBuffer.empty[(Int, Int, Double, Circle)]

def addCircle(x: Int, y: Int, radius: Double, circle: Circle): Unit

= {

items += ((x, y, radius, circle))

}

def draw(): Unit = {

items.foreach {

case (x, y, radius, circle) =>

System.out.println(s"Drawing a circle at ($x, $y) with radius

$radius: $circle")

}

}

}

Graphic类实际上会保存我们的圈子以及与它们相关的所有其他数据。 上图中的客户端在我们的代码中没有特定的表示 - 它只是使用工厂获取圆圈的代码。 类似地,Graphic对象将通过程序检索圆形对象,而不是通过对客户端的显式访问。 以下是我们的示例中如何实现所有这些:

 

object FlyweightExample {

def main(args: Array[String]): Unit = {

val graphic = new Graphic

graphic.addCircle(1, 1, 1.0, Circle(Green))

graphic.addCircle(1, 2, 1.0, Circle(Red))

graphic.addCircle(2, 1, 1.0, Circle(Blue))

graphic.addCircle(2, 2, 1.0, Circle(Green))

graphic.addCircle(2, 3, 1.0, Circle(Yellow))

graphic.addCircle(3, 2, 1.0, Circle(Magenta))

graphic.addCircle(3, 3, 1.0, Circle(Blue))

graphic.addCircle(4, 3, 1.0, Circle(Blue))

graphic.addCircle(3, 4, 1.0, Circle(Yellow))

graphic.addCircle(4, 4, 1.0, Circle(Red))

graphic.draw()

System.out.println(s"Total number of circle objects created:

${Circle.circlesCreated()}")

}

}

运行后,产生输出如下:

 

 

 

//所有代码如下:

package com.ivan.nikolov.structural.flyweight

 

sealed abstract class Color

case object Red extends Color

case object Green extends Color

case object Blue extends Color

case object Yellow extends Color

case object Magenta extends Color

 

package com.ivan.nikolov.structural.flyweight

 

import scala.collection.mutable.{ListBuffer, Map}

 

class Circle(color: Color) {

System.out.println(s"Creating a circle with $color color.")

override def toString(): String =

s"Circle($color)"

}

 

object Circle {

val cache = Map.empty[Color, Circle]

def apply(color: Color): Circle =

cache.getOrElseUpdate(color, new Circle(color))

def circlesCreated(): Int = cache.size

}

 

class Graphic {

val items = ListBuffer.empty[(Int, Int, Double, Circle)]

def addCircle(x: Int, y: Int, radius: Double, circle: Circle): Unit = {

items += ((x, y, radius, circle))

}

def draw(): Unit = {

items.foreach {

case (x, y, radius, circle) =>

System.out.println(s"Drawing a circle at ($x, $y) with radius $radius: $circle")

}

}

}

 

object FlyweightExample {

def main(args: Array[String]): Unit = {

val graphic = new Graphic

graphic.addCircle(1, 1, 1.0, Circle(Green))

graphic.addCircle(1, 2, 1.0, Circle(Red))

graphic.addCircle(2, 1, 1.0, Circle(Blue))

graphic.addCircle(2, 2, 1.0, Circle(Green))

graphic.addCircle(2, 3, 1.0, Circle(Yellow))

graphic.addCircle(3, 2, 1.0, Circle(Magenta))

graphic.addCircle(3, 3, 1.0, Circle(Blue))

graphic.addCircle(4, 3, 1.0, Circle(Blue))

graphic.addCircle(3, 4, 1.0, Circle(Yellow))

graphic.addCircle(4, 4, 1.0, Circle(Red))

graphic.draw()

System.out.println(s"Total number of circle objects created: ${Circle.circlesCreated()}")

}

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

开心自由天使

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值