sheng的学习笔记-设计模式-享元模式

享元模式是一种用于减少对象创建的技术,通过共享内部状态不变的对象来节省内存。在本文中,我们将探讨享元模式的概念、应用场景以及如何通过一个具体的例子(如字符串常量池)来实现。享元工厂负责管理和创建享元对象,确保正确共享。此外,我们还看到了享元模式在池技术中的应用,如数据库连接池和缓冲池。代码示例展示了如何使用享元模式来优化字符串对象的创建和复用。
摘要由CSDN通过智能技术生成

原理图:

 享元模式(Flyweight)定义:运用共享技术来有效地支持大量细粒度对象的复用。它通过共享已经存在的对象来大幅度减少需要创建的对象数量、避免大量相似类的开销,从而提高系统资源的利用率

在面向对象系统的设计何实现中,创建对象是最为常见的操作。这里面就有一个问题:
如果一个应用程序使用了太多的对象, 就会造成很大的存储开销。 特别是对于大量轻量级(细
粒度)的对象,比如在文档编辑器的设计过程中,我们如果为没有字母创建一个对象的话,系统可能会因为大量的对象而造成存储开销的浪费。例如一个字母“ a”在文档中出现了100000 次, 而实际上我们可以让这一万个字母“ a” 共享一个对象, 当然因为在不同的位置可能字母“ a” 有不同的显示效果(例如字体和大小等设置不同), 在这种情况我们可以为将对象的状态分为“外部状态”和“ 内部状态”, 将可以被共享(不会变化)的状态作为内部状态存储在对象中, 而外部对象(例如上面提到的字体、 大小等) 我们可以在适当的时候将外部对象最为参数传递给对象(例如在显示的时候,将字体、大小等信息传递给对象)。

享元模式,第一个想到的应该就是池技术了,String常量池、数据库连接池、缓冲池等等都是享元模式的应用,所以说享元模式是池技术的重要实现方式

代码实现

package design.flyweight;

import java.util.HashMap;

/**
 * 享元模式,第一个想到的应该就是池技术了,
 * String常量池、数据库连接池、缓冲池等等都是享元模式的应用,所以说享元模式是池技术的重要实现方式。
 * 比如我们每次创建字符串对象时,都需要创建一个新的字符串对象的话,
 * 内存开销会很大,所以如果第一次创建了字符串对象“adam“,下次再创建相同的字符串”adam“时,
 * 只是把它的引用指向”adam“,这样就实现了”adam“字符串再内存中的共享
 */
public class FlyweightPattern {
    public static void main(String[] args) {
        int extrinsic = 22;

        Flyweight flyweightX = FlyweightFactory.getFlyweight("X");
        flyweightX.operate(++extrinsic);

        Flyweight flyweightY = FlyweightFactory.getFlyweight("Y");
        flyweightY.operate(++extrinsic);

        Flyweight flyweightZ = FlyweightFactory.getFlyweight("Z");
        flyweightZ.operate(++extrinsic);

        Flyweight flyweightReX = FlyweightFactory.getFlyweight("X");
        flyweightReX.operate(++extrinsic);

        Flyweight unsharedFlyweight = new UnsharedConcreteFlyweight("X");
        unsharedFlyweight.operate(++extrinsic);
    }
}

// Flyweight抽象类 所有具体享元类的超类或接口,通过这个接口,Flyweight可以接受并作用于外部状态。
abstract class Flyweight {

    //内部状态
    public String intrinsic;
    //外部状态
    protected final String extrinsic;

    //要求享元角色必须接受外部状态
    public Flyweight(String extrinsic) {
        this.extrinsic = extrinsic;
    }

    //定义业务操作
    public abstract void operate(int extrinsic);

    public String getIntrinsic() {
        return intrinsic;
    }

    public void setIntrinsic(String intrinsic) {
        this.intrinsic = intrinsic;
    }

}

// ConcreteFlyweight类 继承Flyweight超类或实现Flyweight接口,并为其内部状态增加存储空间
class ConcreteFlyweight extends Flyweight {

    //接受外部状态
    public ConcreteFlyweight(String extrinsic) {
        super(extrinsic);
    }

    //根据外部状态进行逻辑处理
    @Override
    public void operate(int extrinsic) {
        System.out.println("具体Flyweight:" + extrinsic);
    }

}

// 指那些不需要共享的Flyweight子类
class UnsharedConcreteFlyweight extends Flyweight {

    public UnsharedConcreteFlyweight(String extrinsic) {
        super(extrinsic);
    }

    @Override
    public void operate(int extrinsic) {
        System.out.println("不共享的具体Flyweight:" + extrinsic);
    }

}

// 一个享元工厂,用来创建并管理Flyweight对象,主要是用来确保合理地共享Flyweight,
// 当用户请求一个Flyweight时,FlyweightFactory对象提供一个已创建的实例或创建一个实例
class FlyweightFactory {

    //定义一个池容器
    private static HashMap<String, Flyweight> pool = new HashMap<String, Flyweight>();

    //享元工厂
    public static Flyweight getFlyweight(String extrinsic) {
        Flyweight flyweight = null;

        if (pool.containsKey(extrinsic)) {    //池中有该对象
            flyweight = pool.get(extrinsic);
            System.out.print("已有 " + extrinsic + " 直接从池中取---->");
        } else {
            //根据外部状态创建享元对象
            flyweight = new ConcreteFlyweight(extrinsic);
            //放入池中
            pool.put(extrinsic, flyweight);
            System.out.print("创建 " + extrinsic + " 并从池中取出---->");
        }

        return flyweight;
    }
}

运行结果:

创建 X 并从池中取出---->具体Flyweight:23
创建 Y 并从池中取出---->具体Flyweight:24
创建 Z 并从池中取出---->具体Flyweight:25
已有 X 直接从池中取---->具体Flyweight:26
不共享的具体Flyweight:27

参考文章:

简说设计模式——享元模式 - JAdam - 博客园

享元模式(详解版)

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值