Java设计模式——享元模式

概述

在有大量对象时,有可能会造成内存溢出,我们把其中共同的部分抽象出来,如果有相同的业务请求,直接返回在内存中已有的对象,避免重新创建。


版权说明

著作权归作者所有。

商业转载请联系作者获得授权,非商业转载请注明出处。

本文作者:Coding-Naga

发表日期: 2016年4月25日

本文链接:http://blog.csdn.net/lemon_tree12138/article/details/51241598

来源:CSDN

更多内容:分类 >> 设计模式


目录

  • 概述
  • 版权说明
  • 目录
  • 享元模式
    • 定义
    • 单纯享元模式
    • 不共享的享元模式
    • 复合享元模式
  • JDK 里的享元模式
  • Ref

享元模式

定义

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


单纯享元模式

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

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

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<Integer, Flyweight> labels = new HashMap<Integer, Flyweight>();

    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-4
fly1 == fly2 ? false
fly1 == fly3 ? false
fly1 == fly4 ? true
内蕴状态:Unshared
外蕴状态:ExtrinsicState-5

复合享元模式

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

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

ConcreteCompositeFlyweight.java

public class ConcreteCompositeFlyweight implements Flyweight {

    private Map<Integer, Flyweight> labels = new HashMap<Integer, Flyweight>();

    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<Integer, Flyweight> labels = new HashMap<Integer, Flyweight>();

    /**
     * 单纯享元工厂
     */
    public Flyweight factory(String intrinsicState) {
         ... ...
         return fly;
    }

    /**
     * 复合享元工厂
     */
    public Flyweight compositeFactory(List<String> intrinsicStates) {
        ConcreteCompositeFlyweight flyweight = new ConcreteCompositeFlyweight();

        for (String intrinsicState : intrinsicStates) {
            flyweight.add(intrinsicState.hashCode(), factory(intrinsicState));
        }

        return flyweight;
    }
}

测试类

Client.java

public void compositeFlyweight() {
        List<String> intrinsicStates = new ArrayList<String>();
        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 常量池等等);


Ref


时间: 2024-08-29 06:35:14

Java设计模式——享元模式的相关文章

java设计模式--享元模式

享元模式(flyweight) 当需要有很多完全相同或相似的对象需要创建的时候,主要是相似的时候,我们可以用享元模式.尽可能少创建对象,节省内存. 享元模式主要有4中角色 1.享元的工厂 2.抽象享元对象 2.内部状态对象:可以共享的 3.外部状态对象:不可以共享的 下面以围棋的棋子为例:每个棋子都是一个对象,但是每个棋子的大部分都一样,只有颜色,摆放位置不一样,这样就没必要每个棋子都创建一个对象,把相同的和不同的分离开来. //享元类抽象 public interface FlyWeight

JAVA 设计模式 享元模式

用途 享元模式 (Singleton) 运用共享技术有效地支持大量细粒度的对象. 结构 图-享元模式结构图 Flywight : 它是所有具体享元类的超类或接口,通过这个接口,Flyweight 可以接受并作用于外部状态. abstract class Flyweight {     public abstract void Operation(int extrinsicstates); } ConcreteFlyweight :  是继承 Flyweight 超类或实现 Flyweight 接

设计模式——享元模式

Flyweight 直译为蝇量.就其表示的模式来说,翻译成享元,确实是不错的 package designpattern.structure.flyweight; public interface Flyweight { void action(int arg); } package designpattern.structure.flyweight; public class FlyweightImpl implements Flyweight { public void action(int

8. 星际争霸之php设计模式--享元模式

题记==============================================================================本php设计模式专辑来源于博客(jymoz.com),现在已经访问不了了,这一系列文章是我找了很久才找到完整的,感谢作者jymoz的辛苦付出哦! 本文地址:http://www.cnblogs.com/davidhhuan/p/4248186.html============================================

java 之 享元模式(大话设计模式)

笔者很少用到享元模式,在笔者看来,享元模式解决内存问题用的应该会比较多,java中我们常用的String就是利用享元模式的思想来解决内存问题的 先看下类图 大话设计模式-类图 在看下笔者的demo /** * 网站接口 */ public interface IWeb { public void sayMyself(); } /** * 网站实现类 */ public class CurrentWeb implements IWeb{ private String name; public Cu

[工作中的设计模式]享元模式模式FlyWeight

一.模式解析 Flyweight在拳击比赛中指最轻量级,即“蝇量级”或“雨量级”,这里选择使用“享元模式”的意译,是因为这样更能反映模式的用意.享元模式是对象的结构模式.享元模式以共享的方式高效地支持大量的细粒度对象. 享元模式:主要为了在创建对象时,对共有对象以缓存的方式进行保存,对外部对象进行单独创建 模式要点: 1.享元模式中的对象分为两部分:共性部分和个性化部分,共性部分就是每个对象都一致的或者多个对象可以共享的部分,个性化部分指差异比较大,每个类均不同的部分 2.共性部分的抽象就是此模

设计模式-享元模式

***********************************************声明****************************************************** 原创作品,出自 "晓风残月xj" 博客,欢迎转载,转载时请务必注明出处(http://blog.csdn.net/xiaofengcanyuexj). 由于各种原因,可能存在诸多不足,欢迎斧正! *******************************************

小菜学设计模式——享元模式

背景 如果一个应用程序中使用了大量的对象,而大量的这些对象造成了恨得的存储开销时就应该考虑这个新是设计模式:享元模式. 1.使用意图 最大限度地减少了尽可能与其他类似的对象多的数据共享内存的使用,换句话说就是通过共享对象达到系统内维护的对象数量减少从而降低了系统的开销.因为是细粒度的控制,所以享元模式不是控制整个实例共享,那为何不用单例呢?而是只是共享对象的部分,不共享的部分称为对象的外部状态,需要外部动态修改这个共享对象. 2.生活实例 围棋的棋子,如果用编程去实现的话,势必要new出很多实例

iOS设计模式——享元模式

公共交通(如公共汽车)已有一百多年的历史了.大量去往相同方向的乘客可以分担保有和经营车辆(如公共汽车)的费用.公共汽车有多个站台,乘客沿着路线在接近他们目的地的地方上下车.到达目的地的费用仅与行程有关.跟保有车辆相比,乘坐公共汽车要便宜得多.这就是利用公共资源的好处. 在面向对象软件设计中,我们利用公共对象不仅能节省资源还能提高性能.比方说,某个人物需要一个类的一百万个实例,但我们可以把这个类的一个实例让大家共享,而把某些独特的信息放在外部,节省的资源可能相当可观(一个实例与一百万个实例的差别)