zoukankan      html  css  js  c++  java
  • 深入探索Java设计模式(四)之享元模式

    享元模式适用于需要大量相同类型对象的情况。在此,设计布局可以减少创建多个对象的方式。对象在运行时会消耗资源,因此最好在内存中使用较少的对象。它减少了内存占用并利用了程序的整体性能。本文是在学习完优锐课JAVA架构VIP课程—【框架源码专题】中《学习源码中的优秀设计模式》后写下的学习感悟。通过Java中的一个简单示例深入研究了这种模式。

    深入探索Java设计模式(一)之单例模式

    深入探索Java设计模式(二)之策略模式

    深入探索Java设计模式(三)之装饰器模式

    总览

    轻量级模式减少了重复数据的使用。通常的做法是将对象设计成细粒度以利用其使用的灵活性。但是,问题是对象在运行时会消耗资源。粒度会不利地影响应用程序的性能,因为需要将运行时对象容纳在更大的内存集中。每个对象不仅消耗内存,而且消耗CPU周期。在这种情况下,轻量化模式可以通过减少细粒度对象的重复实例化来解决。

    享元模式Flyweight Pattern

    享元模式分为两部分:

    • 内部的:这是独立的部分,数据存储在对象中,与享元模式上下文无关。结果,它对于所有相同的固有数据都是可共享的,因此可以用享元模式对象替换。
    • 外在的: 这是从属部分,其中保留了举重对象的上下文信息。这是不可共享的。状态由客户端对象存储,并根据要求传递给享元模式对象。

     

    享元模式的使用

    在我们有许多表示相同值的对象的情况下,这很有用。因此,它使不可变对象的值可共享。例如,在下面的代码片段中观察Java标准库的Integer包装器类的valueOf()方法如何检查给定参数的值。

    1 public static Integer valueOf(int i) {
    2    if (i >= IntegerCache.low && i <= IntegerCache.high)
    3       return IntegerCache.cache[i + (-IntegerCache.low)];
    4    return new Integer(i);
    5 }

    如果该值先前已缓存,则该方法将返回构造函数实例,而不是创建一个新对象。因为缓存是在静态块中初始化的,所以仅在第一次调用时才创建Integer实例。请注意,IntegerCache类是在Integerclass中定义的私有静态类。

     1 private static class IntegerCache {
     2    // ...
     3    static {
     4       // ...
     5       cache = new Integer[(high - low) + 1];
     6       int j = low;
     7       for (int k = 0; k < cache.length; k++)
     8          cache[k] = new Integer(j++);
     9       // Range [-128, 127] must be interned (JLS7 5.1.7)
    10       assert IntegerCache.high >= 127;
    11    }
    12    // ...
    13 }

    现在,我们可以测试Integer类是否创建两个不同的对象(如果值相同)。将图1中的输出与以下代码进行比较。

     1 public class JustForTesting {
     2    public static void main(String[] args){
     3       final Integer intObj1 = Integer.valueOf(10);
     4       final Integer intObj2 = Integer.valueOf(10);
     5       System.out.println("First Case");
     6       if (intObj1 == intObj2){
     7          System.out.println("If the values are same " +
     8             "then the objects are also same.");
     9       } else {
    10          System.out.println("If the values are different " +
    11             "then the objects are also distinct.");
    12       }
    13       // Now, if we change the same value to a different
    14       // value, it becomes two distinct objects
    15  
    16       final Integer intObj3 = Integer.valueOf(10);
    17       final Integer intObj4 = Integer.valueOf(20);
    18       System.out.println("Second Case");
    19       if (intObj3 == intObj4){
    20          System.out.println("If the values are same " +
    21             "then the objects are also same.");
    22       } else {
    23          System.out.println("If the values are different " +
    24             "then the objects are also distinct.");
    25       }
    26    }
    27 }

    输出

     1:前面代码的输出

     

    实现享元模式

    这是享元模式的简单实现。观察如何限制具有相同值的对象创建新对象,而不是提供池中已经存在的对象的副本。工厂中的对象池充当保留享元模式实例的缓存。

     1 package testpattern;
     2 public class Car {
     3    private String color;
     4    public Car(String color){
     5       this.color = color;
     6       System.out.println("Painted with "+color+" color.");
     7    }
     8    public String getColor() {
     9       return color;
    10    }
    11 }
    12 package testpattern;
    13 import java.util.ArrayList;
    14 import java.util.List;
    15 public class CarFactory {
    16    private List<Car> carpool = new ArrayList<>();
    17    public Car getFlyweightCar(String color) {
    18       for (Car c: carpool) {
    19          if (c.getColor().equals(color)){
    20             System.out.println(color +
    21                " car is already in the pool!");
    22             return c;
    23          }
    24       }
    25       Car car = new Car(color);
    26       carpool.add(car);
    27       return car;
    28    }
    29 }
    30 package testpattern;
    31 public class App {
    32    public static void main(String[] args) {
    33       CarFactory cf = new CarFactory();
    34       cf.getFlyweightCar("RED");
    35       cf.getFlyweightCar("BLUE");
    36       cf.getFlyweightCar("GREEN");
    37       cf.getFlyweightCar("PURPLE");
    38       cf.getFlyweightCar("RED");
    39       cf.getFlyweightCar("BLUE");
    40       cf.getFlyweightCar("BLACK");
    41    }
    42 }

    输出

     2:享元模式实现的输出

     

    结论

    享元模式是在许多情况下使用的常见模式,有时程序员会在不知不觉中使用它。这种模式说明了我们如何使用许多内存不足的对象。如前所述,我们必须始终尽可能利用不变的Integer类的valueOf方法,因为当我们调用new时,即使缓存包含相同的对象,也会创建一个新实例。正如我们已经讨论过的那样,valueOf方法还可以工作。这是使用享元模式的优势。

    感谢阅读!欢迎留言。想更深入探讨学习也欢迎私信我。下篇继续~

    深入探索Java设计模式(五)之构建器模式

  • 相关阅读:
    HttpClient 教程 (四)
    HttpClient 教程 (三)
    HttpClient 教程 (二)
    HttpClient 教程 (一)
    git还原本地提交的某个历史记录
    ExtJS下拉列表使用方法(异步传输数据)
    Struts整合ExtJS
    既有post提交又有get提交时的后台处理办法
    Ajax调用查看页面的后台返回json格式数据
    如何在VS中快速导入新的源码以及文件夹
  • 原文地址:https://www.cnblogs.com/youruike-/p/12072935.html
Copyright © 2011-2022 走看看