【设计模式】第十一章:享元模式详解及应用案例

这篇具有很好参考价值的文章主要介绍了【设计模式】第十一章:享元模式详解及应用案例。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

系列文章

【设计模式】七大设计原则
【设计模式】第一章:单例模式
【设计模式】第二章:工厂模式
【设计模式】第三章:建造者模式
【设计模式】第四章:原型模式
【设计模式】第五章:适配器模式
【设计模式】第六章:装饰器模式
【设计模式】第七章:代理模式
【设计模式】第八章:桥接模式
【设计模式】第九章:外观模式 / 门面模式
【设计模式】第十章:组合模式
【设计模式】第十一章:享元模式
【设计模式】第十二章:观察者模式
【设计模式】第十三章:模板方法模式
【设计模式】第十四章:策略模式
【设计模式】第十五章:责任链模式
【设计模式】第十六章:迭代器模式
【设计模式】第十七章:状态模式
【设计模式】第十八章:备忘录模式
【设计模式】第十九章:访问者模式
【设计模式】第二十章:解释器模式
【设计模式】第二十一章:命令模式
【设计模式】第二十二章:中介者模式



一、定义

摘自百度百科: 它使用共享物件,用来尽可能减少内存使用量以及分享资讯给尽可能多的相似物件;它适合用于只是因重复而导致使用无法令人接受的大量内存的大量物件。通常物件中的部分状态是可以分享。常见做法是把它们放在外部数据结构,当需要使用时再将它们传递给享元。


二、角色分类

抽象享元类(Flyweight)

通常是一个接口或抽象类,其声明了具体享元类的公共方法,这些方法可以向外界提供享元对象的内部数据或内部状态,同时也可以通过这些方法来设置外部数据或外部状态

具体享元类(Concrete Flyweight)

它实现了抽象享元类,它的实例被称为享元对象;在具体享元类内部状态提供了存储空间。通常我们可以结合单例模式来设计具体享元类,为每一个具体享元类提供唯一的享元对象。

非共享具体享元类(Unshared Concrete Flyweight)

不能被共享的子类可被设计为非共享具体享元类,当需要一个非共享具体享元类的对象时可以直接通过实例化创建

享元工厂类(Flyweight Factory)

该类主要用于创建和管理享元对象,它针对抽象享元类变成,将各种类型的具体享元对象存储在一个享元池中,享元池一般设计为一个存储键值对的集合(也可以是其他类型的集合),可以结合工厂模式进行设计

客户角色(Client)

具体调用方法的角色


三、实现方式

UML图

【设计模式】第十一章:享元模式详解及应用案例,设计模式,设计模式,享元模式

单纯享元模式

抽象享元类(Flyweight)

public interface Flyweight {
  public void operate(String type);
}

具体享元类(Concrete Flyweight)和非共享具体享元类(Unshared Concrete Flyweight)

public class CharacterFlyWeight implements Flyweight {
  // 内部状态是不变的,外部状态是变化的
  // 然后通过共享不变的部分,达到减少对象数量并节约内存的目的
  private String name;

  /**
   * 外部状态(非享元)
   * @param name
   */
  public CharacterFlyWeight(String name) {
    this.name = name;
  }

  /**
   * 具体享元+非享元结合
   * @param type
   */
  @Override
  public void operate(String type) {
    System.out.println("姓名 = " + name);
    System.out.println("属性 = " + type);
  }
}

享元工厂(Flyweight Factory)

public class FlyweightFactory {
  // 由工厂方法产生所需要的享元对象
  private Map<String, Flyweight> characterPool = new HashMap<>();

  public Flyweight factory(String user) {
    // 先从缓存中查找对象
    Flyweight flyweight = characterPool.get(user);
    if (null == flyweight) {
      // 如果对象不存在则创建一个新对象
      flyweight = new CharacterFlyWeight(user);
      // 将新对象添加到缓存中
      characterPool.put(user, flyweight);
    }
    return flyweight;
  }
}

客户角色(Client)

public class Client {
  public static void main(String[] args) {
    FlyweightFactory factory = new FlyweightFactory();
    Flyweight flyweightA = factory.factory("小A");
    flyweightA.operate("文静");

    Flyweight flyweightB = factory.factory("小B");
    flyweightB.operate("腼腆");

    Flyweight flyweightC = factory.factory("小A");
    flyweightC.operate("活泼");

    System.out.println(flyweightA == flyweightC); //true
    
  }
}

运行结果

姓名 = 小A
属性 = 文静
姓名 = 小B
属性 = 腼腆
姓名 = 小A
属性 = 活泼
true

复合享元模式

抽象享元角色(Flyweight)

public interface Flyweight {
  public void operate(String type);
}

具体享元角色(Concrete Flyweight)和非共享具体享元角色(Unshared Concrete Flyweight)

public class CharacterFlyweight implements Flyweight {
  // 内部状态是不变的,外部状态变化
  // 通过共享不变的部分,达到减少对象数量并节约内存的目的
  private String name;

  /**
   * 外部状态(非享元)
   * @param name
   */
  public CharacterFlyweight(String name) {
    this.name = name;
  }

  /**
   * 具体享元和非享元结合
   * @param type
   */
  @Override
  public void operate(String type) {
    System.out.println("姓名 = " + name);
    System.out.println("属性 = " + type);
  }
}

复合享元角色(Composite Concrete Flyweight)

public class CharacterCompositeFlyweight implements Flyweight {
  private Map<String, Flyweight> files = new HashMap<>();

  /**
   * 增加一个新的单纯享元对象到集合里
   */
  public void add(String key, Flyweight flyweight) {
    files.put(key, flyweight);
  }

  /**
   * 外部状态作为参数传入到方法中
   */
  @Override
  public void operate(String type) {
    Flyweight flyweight;
    for (String key : files.keySet()) {
      flyweight = files.get(key);
      flyweight.operate(type);
    }
  }
}

享元工厂角色(Flyweight Factory)

public class FlyweightFactory {
  private Map<String, Flyweight> characterPool = new HashMap<>();

  /**
   * 复合工厂方法
   * 一种用于提供单纯享元对象,另一种提供复合享元对象
   */
  public Flyweight factory(List<String> compositeState) {
    CharacterCompositeFlyweight compositeFlyweight = new CharacterCompositeFlyweight();
    compositeState.forEach(any -> compositeFlyweight.add(any, this.factory(any)));
    return compositeFlyweight;
  }

  /**
   * 单纯工厂方法
   * 提供所需要的享元对象
   */
  public Flyweight factory(String user) {
    // 先从缓存中查找对象
    Flyweight flyweight = characterPool.get(user);
    if (null == flyweight) {
      // 如果对象不存在则创建一个新对象
      flyweight = new CharacterFlyweight(user);
      // 将新对象添加到缓存中
      characterPool.put(user, flyweight);
    }
    return flyweight;
  }
  
}

客户角色(Client)

public class Client {
  public static void main(String[] args) {
    List<String> compositeState = new ArrayList<String>();
      compositeState.add("小A");
      compositeState.add("小B");
      compositeState.add("小C");
      compositeState.add("小B");
      compositeState.add("小A");

      FlyweightFactory flyFactory = new FlyweightFactory();
      Flyweight compositeFly1 = flyFactory.factory(compositeState);
      Flyweight compositeFly2 = flyFactory.factory(compositeState);
      compositeFly1.operate("梦游中...");

      System.out.println("---------------------------------");
      System.out.println("复合享元模式是否可以共享对象:" + (compositeFly1 == compositeFly2)); //false

      String user = "小A";
      Flyweight fly1 = flyFactory.factory(user);
      Flyweight fly2 = flyFactory.factory(user);
      System.out.println("单纯享元模式是否可以共享对象:" + (fly1 == fly2)); //true
  }
}

运行结果

姓名 = 小B
属性 = 梦游中...
姓名 = 小A
属性 = 梦游中...
姓名 = 小C
属性 = 梦游中...
---------------------------------
复合享元模式是否可以共享对象:false
单纯享元模式是否可以共享对象:true

四、应用场景

以下部分内容摘自菜鸟教程

意图: 运用共享技术有效地支持大量细粒度的对象。

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

何时使用:

  1. 系统中有大量对象。
  2. 这些对象消耗大量内存。
  3. 这些对象的状态大部分可以外部化。
  4. 这些对象可以按照内蕴状态分为很多组,当把外蕴对象从对象中剔除出来时,每一组对象都可以用一个对象来代替。
  5. 系统不依赖于这些对象身份,这些对象是不可分辨的。

如何解决: 用唯一标识码判断,如果在内存中有,则返回这个唯一标识码所标识的对象。

关键代码: 用 HashMap 存储这些对象。

应用实例:

  1. JAVA 中的 String,如果有则返回,如果没有则创建一个字符串保存在字符串缓存池里面。
  2. 数据库的连接池。

使用场景:

  1. 系统有大量相似对象。
  2. 需要缓冲池的场景。

注意事项:

  1. 注意划分外部状态和内部状态,否则可能会引起线程安全问题。
  2. 这些类必须有一个工厂对象加以控制。

五、优缺点

优点

大大减少对象的创建,降低系统的内存,使效率提高。

缺点

提高了系统的复杂度,需要分离出外部状态和内部状态,而且外部状态具有固有化的性质,不应该随着内部状态的变化而变化,否则会造成系统的混乱。


推荐

关注博客和公众号获取最新文章

Bummon’s Blog | Bummon’s Home | 公众号文章来源地址https://www.toymoban.com/news/detail-536902.html

到了这里,关于【设计模式】第十一章:享元模式详解及应用案例的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【享元设计模式详解】C/Java/JS/Go/Python/TS不同语言实现

    享元模式(Flyweight Pattern),是一种结构型设计模式。主要用于减少创建对象的数量,以减少内存占用和提高性能。它摒弃了在每个对象中保存所有数据的方式,通过共享多个对象所共有的相同状态,让你能在有限的内存容量中载入更多对象。 当程序需要生成数量巨大的相似

    2023年04月10日
    浏览(39)
  • 【设计模式】第十五章:责任链模式详解及应用案例

    【设计模式】七大设计原则 【设计模式】第一章:单例模式 【设计模式】第二章:工厂模式 【设计模式】第三章:建造者模式 【设计模式】第四章:原型模式 【设计模式】第五章:适配器模式 【设计模式】第六章:装饰器模式 【设计模式】第七章:代理模式 【设计模式

    2024年02月13日
    浏览(47)
  • 【设计模式】第十二章:观察者模式详解及应用案例

    【设计模式】七大设计原则 【设计模式】第一章:单例模式 【设计模式】第二章:工厂模式 【设计模式】第三章:建造者模式 【设计模式】第四章:原型模式 【设计模式】第五章:适配器模式 【设计模式】第六章:装饰器模式 【设计模式】第七章:代理模式 【设计模式

    2024年02月13日
    浏览(41)
  • 设计模式:享元模式

    首先我们需要简单了解一下什么是享元模式。 享元模式(Flyweight Pattern) :主要用于减少创建对象的数量,以减少内存占用和提高性能。享元模式的重点就在这个享字,通过一些共享技术来减少对象的创建,实际上Java中String值的存储,Volley中的 ByteArrayPool 也使用到了享元模式,

    2024年02月08日
    浏览(45)
  • 设计模式-享元模式

    享元模式(Flyweight Pattern)是一种结构型设计模式,主要用于减少创建大量相似对象对内存资源的消耗,通过共享这些对象来提高程序性能和系统资源利用率。在实际应用场景中string就是使用了享元模式,string a = “123”; string b = “123”; 我们假设有一个场景是需要创建大量的

    2024年01月24日
    浏览(43)
  • 设计模式——享元模式

    享元模式(Flyweight Pattern)是池技术的重要实现方式。 使用共享对象可以有效地支持大量的细粒度对象。 优点 可以大大减少应用程序创建对象的数量,降低程序内存占用。 缺点 提高了系统的复杂度,需要分离出享元对象的外部状态(key)和内部状态(对象属性),并且外部

    2024年02月16日
    浏览(39)
  • 设计模式(22)享元模式

    一、介绍: 1、定义:享元模式(Flyweight Pattern)主要用于减少创建对象的数量,以减少内存占用和提高性能。这种类型的设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结构的方式。 2、组成结构: (1)Flyweight(抽象享元类):通常是一个接口或

    2024年02月07日
    浏览(43)
  • 设计模式之享元模式

    本文看下一种结构型设计模式,享元模式。 当程序需要大量的重复对象,并且这些大量的重复对象只有部分属性不相同,其他都是相同的时候,就可以考虑使用享元设计模式设计模式来实现。典型的如围棋游戏中的棋子,除了颜色和位置不同外,其他都相同。射击游戏中的子

    2024年02月17日
    浏览(46)
  • 【23种设计模式】享元模式【⭐】

    个人主页 :金鳞踏雨 个人简介 :大家好,我是 金鳞 ,一个初出茅庐的Java小白 目前状况 :22届普通本科毕业生,几经波折了,现在任职于一家国内大型知名日化公司,从事Java开发工作 我的博客 :这里是CSDN,是我学习技术,总结知识的地方。希望和各位大佬交流,共同进

    2024年02月09日
    浏览(49)
  • 设计模式-享元模式(Flyweight)

    享元模式(Flyweight Pattern)是一种结构型设计模式,它的主要目标是减少应用程序中对象的数量,以节省内存和提高性能。这一模式适用于对象数量庞大且相似的情况,通过共享内部状态来减少对象的创建。 在本篇博客中,我们将详细介绍享元模式的概念,并提供一个简单的

    2024年02月09日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包