zoukankan      html  css  js  c++  java
  • 【设计模式

     1、模式简介

      当系统中存在大量对象时,非常容易造成内存溢出。为了解决这个问题,我们把这些对象中共有的部分抽象出来,如果有相同的业务请求,则直接返回在内存中已有的对象,避免重新创建,这就是享元模式。

      享元模式(FlyweightPattern)主要用于减少创建对象的数量,以减少内存占用和提高性能,即它提供了减少对象数量从而改善应用所需的对象结构的方式。享元模式尝试重用现有的同类对象,如果未找到匹配的对象,则创建新对象。

      例如,JAVA中的String使用的就是享元模式:

    public class Test {
       public static void main(String[] args) {
          String a = "abc";
          String b = "abc";
          System.out.println(a == b);
       }
    }
    // 返回值:true

      又如,一个编辑器中如果只能输入大小写的字母,则有52个字符可以输入,此时我们只需要在编辑器中存储52个字符对象,而不需要每输入一个字符就创建一个对象。

      享元模式的UML图:

     

    享元模式的适用场景:

    • 当系统中有大量对象时;
    • 当这些对象基本相似时;
    • 当这些对象会消耗大量内存时;
    • 当这些对象需要使用缓冲池管理时。

    享元模式的使用方法:

      享元模式通常使用一个工厂管理,在工厂中维护一个HashTable或HashMap,使用唯一标识来存放和取出对象。另外还可以对工厂使用单例模式,保证项目中只有一个工厂。

    享元模式的优点:

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

    享元模式的缺点:

      提高了系统的负责度,需要分离出外部状态和内部状态,外部状态不应该随着内部状态的变化而变化,否则会造成系统的混乱。

    2、实例

      我们以上面说的编辑器的例子为需求,要求编辑器中只能输入字符,使用享元模式进行管理。

      享元接口:

    public interface MyChar {
       String showMyChar();
    }

      享元实现类:

    public class MyCharImpl implements MyChar {
       private Character c;
     
       public MyCharImpl(Character c) {
          this.c = c;
       }
     
       @Override
       public String showMyChar() {
          return this.c + "";
       }
    }

      享元工厂:

    public class MyCharFactory {
       private static MyCharFactory instance;
     
       private Map<Character, MyChar> charMap;
     
       private MyCharFactory() {
          this.charMap = new HashMap<Character, MyChar>();
       }
     
       /**
        * 单例
        */
       public static MyCharFactory getInstance() {
          if (instance == null) {
             synchronized (MyCharFactory.class) {
                if (instance == null) {
                    instance = new MyCharFactory();
                }
             }
          }
          return instance;
       }
     
       /**
        * 根据字符的键获取字符对象
        */
       public MyChar getMyChar(Character character) {
          MyChar c = charMap.get(character);
          if (c == null) {
             c = new MyCharImpl(character);
             charMap.put(character, c);
          }
          return c;
       }
     
       /**
        * 获取Map中存储的字符的数量
        */
       public int getCharCount() {
          return charMap.size();
       }
    }

      测试类:

    public class Test {
       public static void main(String[] args) {
          MyChar char1;
          MyChar char2;
          MyChar char3;
          MyChar char4;
          MyChar char5;
          MyChar char6;
     
          char1 = MyCharFactory.getInstance().getMyChar(new Character('a'));
          System.out.println("获取享元字符:" + char1.showMyChar());
          System.out.println("当前享元字符数量:" + MyCharFactory.getInstance().getCharCount());
          char2 = MyCharFactory.getInstance().getMyChar(new Character('b'));
          System.out.println("获取享元字符:" + char2.showMyChar());
          System.out.println("当前享元字符数量:" + MyCharFactory.getInstance().getCharCount());
          char3 = MyCharFactory.getInstance().getMyChar(new Character('c'));
          System.out.println("获取享元字符:" + char3.showMyChar());
          System.out.println("当前享元字符数量:" + MyCharFactory.getInstance().getCharCount());
          char4 = MyCharFactory.getInstance().getMyChar(new Character('a'));
          System.out.println("获取享元字符:" + char4.showMyChar());
          System.out.println("当前享元字符数量:" + MyCharFactory.getInstance().getCharCount());
          char5 = MyCharFactory.getInstance().getMyChar(new Character('a'));
          System.out.println("获取享元字符:" + char5.showMyChar());
          System.out.println("当前享元字符数量:" + MyCharFactory.getInstance().getCharCount());
          char6 = MyCharFactory.getInstance().getMyChar(new Character('d'));
          System.out.println("获取享元字符:" + char6.showMyChar());
          System.out.println("当前享元字符数量:" + MyCharFactory.getInstance().getCharCount());
       }
    }

      运行结果如下图所示:

      最后贴出享元模式的GitHub代码地址:【GitHub - FlyWeight】

  • 相关阅读:
    WebForm跨页面传值---内置对象
    后台获得集合,变成json字符串,放到EL表达式,js进行获取遍历
    Delphi 编写DLL动态链接库文件的知识和样例(有详细步骤,很清楚)
    DELPHI美化界面(2009开始TPanel增加了ParentBackGround)
    在Delphi中创建线程,请一定使用BeginThread()代替CreateThread()创建线程!(更好的管理异常)
    delphi中最小化其他程序及所有程序最小化(使用 shell.minimizeAll 和自己寻找窗口这两种办法)
    电脑睡眠状态(ACPI规范定义了七个状态,使用powercfg -a进行查看)
    javascript
    Master-Worker模式
    程序员的基础和解决问题的思维
  • 原文地址:https://www.cnblogs.com/itgungnir/p/6211136.html
Copyright © 2011-2022 走看看