博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
设计模式(十三)享元模式
阅读量:6176 次
发布时间:2019-06-21

本文共 5507 字,大约阅读时间需要 18 分钟。

定义

享元模式是一种结构型模式,运用共享技术有效地支持大量细粒度的对象。

单纯享元模式

在享元模式中,就其定义我们可以构建出单纯的享元模式。下图是单纯享元模式的类图:

在单纯的享元模式中,需要给出一个抽象接口,以规定出所有具体享元角色需要实现的方法。实现如下:

Flyweight.java

public interface Flyweight {    public void operation(String state);}复制代码

对于享元部分,ConcreteFlyweight 必须是可共享的,它保存的任何状态都必须是内部(intrinsic),ConcreteFlyweight 必须和它的应用环境场合无关。比如字符串 “Hello” 就无需关心使用它的场合,它是一个不可变的对象。

ConcreteFlyweight.java

public class ConcreteFlyweight implements Flyweight {    private String intrinsicState = null;    /**     * 构造函数 内蕴状态作为参数传入     */    public ConcreteFlyweight(String _intrinsicState) {        this.intrinsicState = _intrinsicState;    }    /**     * 外蕴状态作为参数传入方法中 改变方法的行为 但是并不改变对象的内蕴状态     */    @Override    public void operation(String extrinsicState) {        System.out.println("内蕴状态:" + intrinsicState);        System.out.println("外蕴状态:" + extrinsicState);    }}复制代码

在享元模式中,有一个至关重要的模块就是工厂模块了。在 Flyweight Factory 里维护了一个 Flyweight 池(存放内部状态),Flyweight Factory 就是通过这个 Flyweight 池对整个享元模式进行控制。

FlyweightFactory.java

public class FlyweightFactory {    private Map
labels = new HashMap
(); public Flyweight factory(String intrinsicState) { int hashCode = intrinsicState.hashCode(); Flyweight fly = labels.get(hashCode); if (fly == null) { fly = new ConcreteFlyweight(intrinsicState); labels.put(hashCode, fly); } return fly; }}复制代码

在上面的工厂模块中可以看到,FlyweightFactory 实际上是起到了一个过滤筛选的功能,过滤重复的对象,缓存新对象。

不共享的享元模式

与共享的享元对象相对的就是不共享的享元对象。关于不共享的享元对象,可能你会有一些疑问,既然不共享,为何还要包含到享元模式中来呢?这可能是出于完整性的考虑,或是要某些场景下既要使用共享的享元,又要使用不共享的享元吧。关于这一点本人也还没有完全理解,也有可能根本不需要这一个不共享的享元对象吧。下面是不共享的享元类图:

不共享的享元实现与 ConcreteFlyweight 无异。如下: UnsharedConcreteFlyweight.java

public class UnsharedConcreteFlyweight implements Flyweight {    private String intrinsicState = null;    public UnsharedConcreteFlyweight(String _intrinsicState) {        this.intrinsicState = _intrinsicState;    }    @Override    public void operation(String extrinsicState) {        System.out.println("内蕴状态:" + intrinsicState);        System.out.println("外蕴状态:" + extrinsicState);    }}复制代码

下面是对单纯的享元与不共享的享元进行测试的代码。

Client.java

public class Client {    public static void main(String[] args) {        FlyweightFactory factory = new FlyweightFactory();        Flyweight fly1 = factory.factory("Hello");        fly1.operation("ExtrinsicState-1");        Flyweight fly2 = factory.factory("DesignPattern");        fly2.operation("ExtrinsicState-2");        Flyweight fly3 = factory.factory("Flyweight");        fly3.operation("ExtrinsicState-3");        Flyweight fly4 = factory.factory("Hello");        fly4.operation("ExtrinsicState-4");        System.out.println("fly1 == fly2 ? " + (fly1 == fly2));        System.out.println("fly1 == fly3 ? " + (fly1 == fly3));        System.out.println("fly1 == fly4 ? " + (fly1 == fly4));        Flyweight fly5 = new UnsharedConcreteFlyweight("Unshared");        fly5.operation("ExtrinsicState-5");    }}复制代码
内蕴状态:Hello外蕴状态:ExtrinsicState-1内蕴状态:DesignPattern外蕴状态:ExtrinsicState-2内蕴状态:Flyweight外蕴状态:ExtrinsicState-3内蕴状态:Hello外蕴状态:ExtrinsicState-4fly1 == fly2 ? falsefly1 == fly3 ? falsefly1 == fly4 ? true内蕴状态:Unshared外蕴状态:ExtrinsicState-5复制代码

复合享元模式

在上面的单纯享元中,所有的享元可以说是在同一个分组里。有时候这样的大集合可能并不能发挥出很好的应用功能,所以引入了复合式的享元模式。下面是复合式享元模式类图:

复合式享元相当于多个单纯享元的集合。

也就是说复合享元相当于对单纯享元进行了一个再分组,在复合享元的每个分组里又是一个独立的单纯享元模式。相关关键代码如下:

ConcreteCompositeFlyweight.java

public class ConcreteCompositeFlyweight implements Flyweight {    private Map
labels = new HashMap
(); public void add(int key, Flyweight flyweight) { labels.put(key, flyweight); } @Override public void operation(String extrinsicState) { Flyweight flyweight = null; for (Object key : labels.keySet()) { flyweight = labels.get(key); flyweight.operation(extrinsicState); } }}复制代码

对于其构建工厂也需要进行重新设计,如下:

FlyweightFactory.java

public class FlyweightFactory {    private Map
labels = new HashMap
(); /** * 单纯享元工厂 */ public Flyweight factory(String intrinsicState) { ... ... return fly; } /** * 复合享元工厂 */ public Flyweight compositeFactory(List
intrinsicStates) { ConcreteCompositeFlyweight flyweight = new ConcreteCompositeFlyweight(); for (String intrinsicState : intrinsicStates) { flyweight.add(intrinsicState.hashCode(), factory(intrinsicState)); } return flyweight; }}复制代码

测试类

Client.java

public void compositeFlyweight() {        List
intrinsicStates = new ArrayList
(); intrinsicStates.add("Hello"); intrinsicStates.add("Java"); intrinsicStates.add("DesignPattern"); intrinsicStates.add("Flyweight"); FlyweightFactory factory = new FlyweightFactory(); Flyweight flyweight1 = factory.compositeFactory(intrinsicStates); Flyweight flyweight2 = factory.compositeFactory(intrinsicStates); System.out.println("flyweight1 == flyweight2 ? " + (flyweight1 == flyweight2)); flyweight1.operation("复合享元-1"); flyweight2.operation("复合享元-2"); }复制代码
flyweight1 == flyweight2 ? false内蕴状态:Java外蕴状态:复合享元-1内蕴状态:Flyweight外蕴状态:复合享元-1内蕴状态:Hello外蕴状态:复合享元-1内蕴状态:DesignPattern外蕴状态:复合享元-1内蕴状态:Java外蕴状态:复合享元-2内蕴状态:Flyweight外蕴状态:复合享元-2内蕴状态:Hello外蕴状态:复合享元-2内蕴状态:DesignPattern外蕴状态:复合享元-2复制代码

JDK 里的享元模式

在 JDK 的设计里,也有很享元模式。比如一些常量池的设计(String 常量池、Integer 常量池等等);

note:生如夏花之绚烂,死如秋叶之静美

转载于:https://juejin.im/post/5cd183ab6fb9a03223353f99

你可能感兴趣的文章
Scala并发编程【消息机制】
查看>>
win10下安装Oracle 11g 32位客户端遇到INS-13001环境不满足最低要求
查看>>
AngularJS-01.AngularJS,Module,Controller,scope
查看>>
【MySQL 安装过程1】顺利安装MySQL完整过程
查看>>
Inno Setup入门(二十)——Inno Setup类参考(6)
查看>>
图片自适应
查看>>
amd cmd
查看>>
Linux下的uml画图工具
查看>>
xml返回数组数据
查看>>
约瑟夫问题总结
查看>>
spring mybatis 批量插入返回主键
查看>>
指针函数小用
查看>>
开源力量公开课第二十三期-从SVN到Git,次时代代码管理
查看>>
输入挂
查看>>
升级迁移前,存储过程统计各个用户下表的数据量,和迁移后的比对
查看>>
sql注入分类
查看>>
初识CSS选择器版本4
查看>>
[Hadoop in China 2011] 朱会灿:探析腾讯Typhoon云计算平台
查看>>
JavaScript之数组学习
查看>>
PHP 设置响应头来解决跨域问题
查看>>