设计模式-享元模式

设计模式-享元模式

一. 定义与类型

定义:提供了减少对象数量从而改善应用所需的对象结构的方式,运用共享技术有效地支持大量细粒度的对象

类型:结构性

二. 使用场景

(1) 常常应用于系统底层的开发,以便解决系统的性能问题

(2) 系统有大量相似对象,需要缓冲池的场景

三. 优缺点

优点:

  (1) 减少对象的创建,降低内存中对象的数量,降低系统的内存,提高效率

  (2) 减少内存之外的其他资源占用

缺点:

  (1) 关注内/外状态,关注线程安全问题

  (2) 使系统,程序的逻辑复杂化

四、代码示例

image.png

/** 
 * 享元模式(Flyweight):运用共享的技术有效地支持大量细粒度的对象。 
 *  
 * 主要目的是实现对象的共享,即共享池,当系统中对象多的时候可以减少内存的开销。 
 */  
abstract class FlyWeight {  
    public abstract void method();  
}  
  
/** 
 * 创建持有key的子类 
 */  
class SubFlyWeight extends FlyWeight {  
    private String key;  
  
    public SubFlyWeight(String key) {  
        this.key = key;  
    }  
  
    @Override  
    public void method() {  
        System.out.println("this is the sub method,and the key is " + this.key);  
    }  
}  
  
/** 
 * 享元工厂:负责创建和管理享元对象 
 */  
class FlyweightFactory {  
    private Map<String, FlyWeight> map = new HashMap<String, FlyWeight>();  
  
    /** 
     * 获取享元对象 
     */  
    public FlyWeight getFlyWeight(String key) {  
        FlyWeight flyWeight = map.get(key);  
        if (flyWeight == null) {  
            flyWeight = new SubFlyWeight(key);  
            map.put(key, flyWeight);  
        }  
        return flyWeight;  
    }  
  
    /** 
     * 获取享元对象数量 
     */  
    public int getCount() {  
        return map.size();  
    }  
}  
  
/** 
 * 客户端测试类 
 *  
 * @author Leo 
 */  
public class Test {  
    public static void main(String[] args) {  
        /** 
         * 创建享元工厂 
         */  
        FlyweightFactory factory = new FlyweightFactory();  
        /***** 第一种情况:key相同时 ***************/  
        FlyWeight flyWeightA = factory.getFlyWeight("aaa");  
        FlyWeight flyWeightB = factory.getFlyWeight("aaa");  
        /** 
         * 透过打印结果为true可以知道: 由于key都为"aaa",所以flyWeightA和flyWeightB指向同一块内存地址 
         */  
        System.out.println(flyWeightA == flyWeightB);  
        flyWeightA.method();  
        flyWeightB.method();  
        /** 
         * 享元对象数量:1 
         */  
        System.out.println(factory.getCount());  
  
        /***** 第二种情况:key不相同时 ***************/  
        System.out.println("\n======================================");  
        FlyWeight flyWeightC = factory.getFlyWeight("ccc");  
        /** 
         * 打印结果为false 
         */  
        System.out.println(flyWeightA == flyWeightC);  
        flyWeightC.method();  
        /** 
         * 享元对象数量:2 
         */  
        System.out.println(factory.getCount());  
    }  
} 

打印结果:

true
this is the sub method,and the key is aaa
this is the sub method,and the key is aaa
1
======================================
false
this is the sub method,and the key is ccc

五、常用实例

(1)Integer类就是典型的享元模式的例子

image.png

 Integer.valueOf中有一个IntegerCache,上面的代码中就对传入的值进行判断。如果是从IntegerCache中取出就直接返回,否则就new一个Integer对象。这也就是如果传入的int值不在固定的范围类,它们做==的时候一定是false,因为不是同一个对象。其中low=-128,high=127.
image.png

image.png

还有Long类的valueOf,也是同上的道理。

(2)

tomcat中的GenericObjectPoolConfig连接池