设计模式—享元模式

一、什么是享元模式

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

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

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

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

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

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

三、代码案例:

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

首先是抽象类

复制代码
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)对象的大部分状态都可以外部化,可以将这些外部状态传入对象中。

相关推荐
东阳马生架构3 分钟前
商品中心—1.B端建品和C端缓存的技术文档
java
Chan165 分钟前
【 SpringCloud | 微服务 MQ基础 】
java·spring·spring cloud·微服务·云原生·rabbitmq
LucianaiB8 分钟前
如何做好一份优秀的技术文档:专业指南与最佳实践
android·java·数据库
面朝大海,春不暖,花不开32 分钟前
自定义Spring Boot Starter的全面指南
java·spring boot·后端
得过且过的勇者y33 分钟前
Java安全点safepoint
java
乄夜1 小时前
嵌入式面试高频(5)!!!C++语言(嵌入式八股文,嵌入式面经)
c语言·c++·单片机·嵌入式硬件·物联网·面试·职场和发展
夜晚回家1 小时前
「Java基本语法」代码格式与注释规范
java·开发语言
斯普信云原生组1 小时前
Docker构建自定义的镜像
java·spring cloud·docker
wangjinjin1801 小时前
使用 IntelliJ IDEA 安装通义灵码(TONGYI Lingma)插件,进行后端 Java Spring Boot 项目的用户用例生成及常见问题处理
java·spring boot·intellij-idea
wtg44521 小时前
使用 Rest-Assured 和 TestNG 进行购物车功能的 API 自动化测试
java