问题标签 [flyweight-pattern]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
1 回答
226 浏览

design-patterns - Flyweight模式:UnsharedConcreteFlyweight

下面是享元模式结构图:

在此处输入图像描述

在这里,您可以看到 GoF 解释的 UnsharedConcreteFlyweight:

UnsharedConcreteFlyweight :并非所有 Flyweight 子类都需要共享。享元界面可实现共享;它不强制执行它。UnsharedConcreteFlyweight 对象通常在享元对象结构中的某个级别将 ConcreteFlyweight 对象作为子对象(如 Row 和 Column 类所具有的)。

据我所知,这里Operation需要in extrinsicState作为参数,但就allState成员数据而言,它根本不会使用它。

这是一个好的设计吗?采用您不使用的参数,如果您将使用,那么您将有数据重复。这甚至可能违反了里氏替换原则?

0 投票
1 回答
88 浏览

java - 来自享元的自可移除资源

我正在使用需要关闭的不同资源的应用程序,同时使用反应流。

我有一个基于享元模式的工厂,它保留对对象的引用,它们实现了 AutoCloseable 接口。问题是我在 Autocloseable 类中使用 close() ,这是我的问题:删除对工厂内封闭资源的引用的最佳解决方案是什么?我可以抛出某种事件并在工厂中捕获它​​,还是在每个可以关闭资源的操作之后我应该遍历引用映射并删除关闭的资源?

为了获得更好的上下文:我正在使用发出目录事件(创建、删除文件/目录)的 reactivex Observable,并且在每个订阅者取消订阅它之后,我正在关闭我正在使用的 WatchService。

编辑#1

我的工厂类如下所示:

这是我的 ReactiveStream 类的样子:

如您所见,我有一个工厂,它保留对 ReactiveStream 类的引用,该类在可观察后关闭,将不再被订阅(我这样做的方式是在使用 share 之前使用 doOnUnsubscribe(() -> close()) () 在 observable 上,因此当没有订阅者时,将调用 doOnUnsubscribe)。

我的问题是,如何在工厂关闭后从工厂中删除对已关闭 ReactiveStream 的引用?

编辑#2

这是我创建可观察对象的方式。EventObtainer 是 ReactiveStream 中的嵌套类,它使用 WatchService 需要在每个订阅者停止订阅后关闭。

0 投票
1 回答
255 浏览

java - 如何重用 GUI 对象(享元模式)

在我的 Java 应用程序中,我有一个复杂的 GUI,它有一定的 JPanel(自定义控件)重复,比如说,100 次(实际上它可能更多,但我不想让这个例子太复杂)。这 100 个 JPanel 中的每一个都包含 4 个 JTextBox 控件,它们向用户显示某些值。

一个面板的 JTextBoxes 可能是空的,而在另一个面板中只有一个可能有值,在其他一些中,所有框可能会显示一些数字,你明白了 - 我不知道哪个面板的哪个文本框将包含哪些数据。

现在,为了减少内存占用,我开始学习 Flyweight 设计模式。这似乎正是我需要的东西,但是,如果我保留一个 JPanel 作为种子,并用它来表示其他 99 个面板(只是相应地更改 JTextBox 值),这意味着所有这些面板将共享共同的参考。

在这种情况下,更改其中一个中的 JTextBox 值也会更改所有其他值中的值,对吗?如何克服这个问题,并且仍然保持应用程序的低内存占用?

我错过了什么吗?

0 投票
1 回答
62 浏览

java - Java 中的享元模式在内存管理方面是如何工作的?

我觉得我对设计模式有一个很好的掌握,但是我似乎无法理解一件事,而且在我查看的资源中似乎也没有得到确切的解释。
那个问题是,考虑到对象是独立的实体,数据如何通用,而不是静态数据?

https://www.tutorialspoint.com/design_pattern/flyweight_pattern.htm

在这个例子中,我无法弄清楚优化发生在哪里,因为它看起来好像每次都像往常一样创建对象。

这个代码块似乎是我最好的猜测,因为第一行从 HashMap 检索具有某种颜色的圆,但这会创建一个新的圆实例,没有持久引用圆的颜色。
因此,除非我弄错了,否则没有实际的共享数据,所以我不确定这会如何提供除了在创建期间之外的好处。

0 投票
1 回答
376 浏览

swift - 使用 Swift SceneKit 的享元设计模式。对象重用

我正在构建一个增强现实 iPhone 应用程序,它需要渲染大量的 SceneKit 节点。我想集成Gamma、Helm、Johnson 和 Vlissides在设计模式中描述的享元设计模式。也是这里的教程Flyweight Design Pattern 但是,我遇到了实现以及 Swift 如何处理对象的问题。

TL;DR:在 Swift 中有没有一种方法可以让我不止一次地将它添加SCNNode到 a中,并让它显示在不同的位置?ARSCNView

我有一个名为的类Box,它构建SCNBox了我想利用 Flyweight 的 s;a的内在状态Box维度。外在状态是它的颜色和位置。

盒子类

我有一个工厂类,它使用字典来实现设计,检查以前的对象是否相同颜色,如果是,则重用该对象,否则创建一个新对象。

工厂类

还有一些视图控制器持有一个ARSCNView对象来显示这些框。

但是,这只会产生一个绿色框;正确的那一个。第二个getBox()调用覆盖第一个位置Image below。对于这种模式或 Swift 的实现,是否有人有任何建议可以帮助实现这种对象重用模式?

*旁注:我不需要散列对象的位置及其颜色。因为我会有许多Box不同颜色和位置的 es ,它会破坏重用同一个对象的整个想法。

只有一个绿色盒子

0 投票
0 回答
156 浏览

java - 游戏状态树 - 无法进行深度克隆,需要在不覆盖数据的情况下创建多个状态

对于我的 AI 课程中的一个项目,我们正在巧妙地为游戏制作 AI,但在创建游戏状态树时遇到了麻烦。我们的树由节点表示,其中包含 GameStates,它们本身包含玩家列表(以及所有相应的数据,例如他们的分数、他们手中的牌和他们的玩家编号),游戏的当前状态板,还有一袋剩余的瓷砖可供选择。根节点是当前状态,它通过 Edge 对象连接到子节点,其中包含父节点和子节点,以及将父节点引导到子节点的 Action。该动作包含放置在板上的图块、图块包含的颜色以及将放置图块的六边形网格上的坐标。

我们的问题是,在创建新的游戏状态时,我们正在更新状态中包含的数据,而不是创建游戏状态的副本。通常,我们只会为根的每个子节点制作游戏状态的深层副本,等等。

这就是事情变得棘手的地方。我们的六边形网格库来自 Java 库Hexameter,它是一个六边形网格,其中包含可以包含卫星数据的六边形对象,这是我们用来表示我们放置的瓷砖/颜色的东西。问题在于,由于 satelliteData 指的是原始对象,并且实际上并不包含对象,因此我们无法深度克隆我们的 GameState(据我所知)。

由于我们的最后期限在不到一周的时间内很快就要到了,而且过去几天我们一直在努力解决我们的问题,所以我们最终求助于 StackOverFlow 寻求帮助。看看我们的 GameState 结构:(请注意,下面的所有代码都被删除了 getter、setter 和不相关的方法)

看看我们的两个构造函数——我们的第一个实例化初始游戏状态,第二个接受我们想要在更新游戏时传递的参数。问题是,我们意识到

更改原始状态,而不是新状态。

我们最初考虑做的是在第二个构造函数中,传递我们想要更改的状态,然后为新状态创建新变量并根据前一个状态的值实例化它们。问题是,我们现在没有任何方法可以访问这些。

我们研究了在游戏树中为我们的子节点使用享元,它代表了我们基于动作所做的更改:

我们以这样的方式应用动作来创建下一个 GameState:

如您所见,这并不能正确“克隆”游戏状态。在对 StackOverFlow 进行深入研究后,我们提出了 3 个不错的选择:

  • 通过手动重构我们的代码以具有多个构造函数、getter、setter 和用于创建每个类的副本的方法来进行深度克隆。
  • 使用 Serializable 接口,但是我们从未使用过它,并且由于截止日期,不愿意跳进去尝试解决它。
  • 使用享元模式,尽管它似乎是我们最好的选择(并且显然实现起来很复杂),但我们也从未使用过它。

我在问是否有人有任何“快速修复”,我们可以使用它来获得某种形式的“工作”树,我们可以在(MCTS、A*、ExpectiMax、Greedy 等)上运行基本 AI 以获得某种形式的结果。

0 投票
0 回答
262 浏览

javascript - JavaScript + Node.js。享元模式查询

在学习 Pluralsight 提供的一门设计模式课程时,它触及了享元模式,并在 node.js 中提供了一个示例。

课程中的示例将完全不使用享元与使用由多个字段连接在一起的唯一组合组成的享元进行对比,其中 1m 个对象有 160 个唯一组合。

我更进一步,只为独特的个体值创建享元,将享元的数量从 160 个减少到 15 个。

我的期望是,通过减少使用的享元数量,可以降低内存使用量。在我的测试中并非如此。

我怀疑我在概念上缺少一些东西。

注意我已经包含了一个可以提取并在节点中运行的小提琴。

与任务对象相关的部分详述如下:

http://jsfiddle.net/apc8nrmy/6/

0 投票
1 回答
169 浏览

javascript - 带有 WeakMap 或 WeakSet 的 Javascript Flyweight

我想要一个 Flyweight 对象,所以我创建了一个 Object 并将它的实例存储在 Map 中,如下所示:

问题是,当我不再使用 FlyweightNumber 值时,它仍在内存中,存储在此 Map 中。

由于 WeakMap 和 WeakSet 应该让垃圾收集器在不再使用它时将其清除,我如何编写构造函数来返回 WeakSet 或 WeakMap 中的对象,或者如果不再存储它则创建一个新对象?

0 投票
1 回答
57 浏览

design-patterns - 享元模式困境

这个Flyweight DP 教程很好地解释了 Flyweight 模式。

无论如何,假设我们要更改的字体大小this.height = 200;(假设属性不受保护)。这意味着所有的字体大小都会改变,因为对象是引用类型的。

假设这是一个文本编辑器,我们只想更改特定字母的字体大小(字母的单个实例,而不是全部)。所以现在出现了一个问题,因为如果我们以某种方式改变字典中对象的字体大小,所有出现的地方都会改变。我该如何处理?

0 投票
2 回答
739 浏览

design-patterns - 享元模式 - 非共享具体实例的意义何在?

众所周知,享元模式的UML图中有一个非共享的具体实例,它实现了享元接口。我的问题是,如果它的外部状态毫无意义,它为什么要实现它?我的意思是,对于共享的具体实例,接口是必需的,所以你必须确保可以传递外部状态,但是非共享的呢?难道我们不能轻易不实现接口并达到相同的结果吗?