设计模式—享元模式

一、什么是享元模式

享元模式通过共享技术有效地支持细粒度、状态变化小的对象复用,当系统中存在有多个相同的对象,那么只共享一份,不必每个都去实例化一个对象,极大地减少系统中对象的数量。

比如当前电商项目中在购物车中,可能会有多个相同商品的实例被加入到购物车中,这些商品的信息可能相似。通过享元模式可以共享相同商品的信息对象,减少购物车中的内存消耗。

在了解享元模式之前我们先要了解两个概念:内部状态、外部状态。

  • 内部状态:在享元对象内部不随外界环境改变而改变的共享部分。
  • 外部状态:随着环境的改变而改变,不能够共享的状态就是外部状态。

由于享元模式区分了内部状态和外部状态,所以我们可以通过设置不同的外部状态使得相同的对象可以具备一些不同的特性,而内部状态设置为相同部分。在我们的程序设计过程中,我们可能会需要大量的细粒度对象来表示对象,如果这些对象除了几个参数不同外其他部分都相同,这个时候我们就可以利用享元模式来大大减少应用程序当中的对象。如何利用享元模式呢?这里我们只需要将他们少部分的不同的部分当做参数移动到类实例的外部去,然后再方法调用的时候将他们传递过来就可以了。这里也就说明了一点:

内部状态存储于享元对象内部,而外部状态则应该由客户端来考虑。

三、代码案例:

场景:假如在电商网站的购物车中,对于一些多个相同的商品实例,这些商品信息可能相似,那么就可以共享一些信息对象,减少内存消耗。

首先是抽象类

public  abstract class showPhone {

    public abstract void getPid();  //获取商品pid 只有商品pid不同
}

然后是实现类

public class XmPhone extends showPhone{

    private String pid;

    public XmPhone(String pid){
        this.pid=pid;
    }


    @Override
    public void getPid() {
        System.out.println(pid);
    }

    public void setPid(String pid){
        this.pid=pid;
    }
}

再是享元工厂类

public class showPhoneFactory {

    static HashMap<String,showPhone> hashMap=new HashMap<>();


    public static showPhone getPhone(String key){
        showPhone showPhone=hashMap.get(key);

        if (showPhone==null){
            showPhone=new XmPhone(key); //如果没有则新建一个
            hashMap.put(key,showPhone);//然后放入池中
        }
        return showPhone;
    }



    public void getSize(){
        int size = hashMap.size();
        System.out.println(size);
    }
}

在这里定义了一个HashMap 用来存储各个对象,用户需要对象时,首先从享元池中获取,如果享元池中不存在,则创建一个新的享元对象返回给用户,并在享元池中保存该新增对象。

客户端

public class Test {
    public static void main(String[] args) {
        showPhone phone = showPhoneFactory.getPhone("123");
        System.out.println(phone);

        showPhone phone2 = showPhoneFactory.getPhone("666");
        System.out.println(phone2);

        showPhone phone3 = showPhoneFactory.getPhone("123");
        System.out.println(phone3);
        System.out.println(phone3==phone);

    }
}
//运行结果
com.patterns.flyWeight.XmPhone@396f6598
com.patterns.flyWeight.XmPhone@394e1a0f
com.patterns.flyWeight.XmPhone@396f6598
true

在 Java 中,String 类型就是使用享元模式,String 对象是 final 类型,对象一旦创建就不可改变。而 Java 的字符串常量都是存在字符串常量池中的,JVM 会确保一个字符串常量在常量池中只有一个拷贝。

四、享元模式的优缺点:

1、享元模式的优点:

(1)极大减少系统中对象的个数;

(2)由于使用了外部状态,外部状态相对独立,不会影响到内部状态,所以享元模式使得享元对象能够在不同的环境被共享。

2、享元模式的缺点:

(1)由于享元模式需要区分外部状态和内部状态,使得应用程序在某种程度上来说更加复杂化了。

(2)为了使对象可以共享,需要将享元对象的状态外部化,而读取外部状态使得运行时间变长。

3、适用场景:

(1)如果系统中存在大量的相同或者相似的对象,由于这类对象的大量使用,会造成系统内存的耗费,可以使用享元模式来减少系统中对象的数量。

(2)对象的大部分状态都可以外部化,可以将这些外部状态传入对象中。

相关推荐
graceyun6 分钟前
C语言进阶习题【1】指针和数组(4)——指针笔试题3
android·java·c语言
我科绝伦(Huanhuan Zhou)11 分钟前
Linux 系统服务开机自启动指导手册
java·linux·服务器
旦沐已成舟1 小时前
K8S-Pod的环境变量,重启策略,数据持久化,资源限制
java·docker·kubernetes
S-X-S1 小时前
项目集成ELK
java·开发语言·elk
Ting-yu1 小时前
项目实战--网页五子棋(游戏大厅)(3)
java·java-ee·maven·intellij-idea
程序研6 小时前
JAVA之外观模式
java·设计模式
计算机学姐6 小时前
基于微信小程序的驾校预约小程序
java·vue.js·spring boot·后端·spring·微信小程序·小程序
黄名富6 小时前
Kafka 日志存储 — 日志索引
java·分布式·微服务·kafka
好评笔记6 小时前
AIGC视频生成模型:Stability AI的SVD(Stable Video Diffusion)模型
论文阅读·人工智能·深度学习·机器学习·计算机视觉·面试·aigc
m0_748255026 小时前
头歌答案--爬虫实战
java·前端·爬虫