Absolutely-  
热衷于分享、记录。技术探讨、学习资料,可以加我vx:ddmsiqi ,共同进步!【优锐课】抽丝剥茧,细说架构那些事

享元模式适用于需要大量相同类型对象的情况。在此,设计布局可以减少创建多个对象的方式。对象在运行时会消耗资源,因此最好在内存中使用较少的对象。它减少了内存占用并利用了程序的整体性能。本文是在学习完优锐课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设计模式(五)之构建器模式

posted on 2019-12-20 14:30  Absolutely-  阅读(367)  评论(0编辑  收藏  举报