前言
目前正在出一个设计模式专题
系列教程, 篇幅会较多, 喜欢的话,给个关注❤️ ~
本节给大家讲一下设计模式中的享元模式
,并结合实际业务场景给大家讲解如何使用~
本专题的所有案例代码主要以Java
语言为主, 好了, 废话不多说直接开整吧~
享元模式
享元模式
是一种结构型设计模式,其主要目的是通过共享
尽可能多的对象来减少内存使用
和对象创建
的数量。其核心思想是尽可能地共享对象
,以减少内存
的使用。
在享元模式中
,我们将对象分为两类:内部状态
和外部状态
。内部状态
是指对象不随着外部环境的变化而变化的状态,而外部状态
是指对象随着外部环境的变化而变化的状态。享元模式的重点是共享内部状态
,而外部状态则通过参数
传递。
// 享元工厂类 class ShapeFactory { private static final Map<String, Shape> shapes = new HashMap<>(); // 获取具体形状 public static Shape getShape(String color) { Shape shape = shapes.get(color); if (shape == null) { shape = new Circle(color); shapes.put(color, shape); System.out.println("Creating circle of color : " + color); } return shape; } } // 形状接口 interface Shape { void draw(); } // 具体形状类 class Circle implements Shape { private String color; public Circle(String color) { this.color = color; } @Override public void draw() { System.out.println("Drawing circle of color : " + color); } } // 客户端类 public class Client { private static final String[] colors = { "Red", "Green", "Blue" }; public static void main(String[] args) { for (int i = 0; i < 20; ++i) { Circle circle = (Circle) ShapeFactory.getShape(getRandomColor()); circle.draw(); } } private static String getRandomColor() { return colors[(int) (Math.random() * colors.length)]; } }
在上面的代码中,我们首先定义了一个Shape
接口和一个具体的形状类 Circle
。然后,我们创建了一个享元工厂类 ShapeFactory
,并在其中维护了一个 Map
对象,用于存储不同颜色的圆形对象。当客户端请求一个圆形对象时,我们首先检查该颜色的圆形对象是否已经存在于 Map
对象中。如果存在,我们直接返回该圆形对象;如果不存在,我们创建一个新的圆形对象,并将其添加到 Map 对象中以备后续使用。
最后,我们在客户端类Client
中演示了如何使用享元模式创建不同颜色的圆形对象。在这个例子中,我们模拟了创建20
个圆形对象的场景,但实际上只创建了3
个不同颜色的圆形对象,大大减少了内存的使用。
最佳实践
电商平台中,商品是非常重要的元素之一,每个商品都有自己的属性和信息,比如商品名称、价格、描述、图片等等。但是在一些场景下,会存在大量相同属性的商品实例,这些实例会占用很多内存资源,降低系统性能。
这个时候就可以使用享元模式,将相同的属性提取出来,共享使用,减少内存占用,提高系统性能。
假设一个商品的属性有:名称、价格、描述和图片,我们先定义一个Product
接口:
public interface Product { void showInfo(); }
然后定义具体的商品类ConcreteProduct
public class ConcreteProduct implements Product { private String name; private double price; private String description; private String image; public ConcreteProduct(String name, double price, String description, String image) { this.name = name; this.price = price; this.description = description; this.image = image; } @Override public void showInfo() { System.out.println("名称:" + name); System.out.println("价格:" + price); System.out.println("描述:" + description); System.out.println("图片:" + image); } }
在这个例子中,ConcreteProduct
类包含了所有商品的属性。
为了使用享元模式,我们需要将相同属性的商品实例共享使用,可以使用一个工厂类ProductFactory
来管理商品实例。
public class ProductFactory { private static final Map<String, Product> products = new HashMap<>(); public static Product getProduct(String name, double price, String description, String image) { String key = name + price + description + image; if (products.containsKey(key)) { return products.get(key); } else { Product product = new ConcreteProduct(name, price, description, image); products.put(key, product); return product; } } }
在工厂类中,我们使用一个Map
来存储已经创建的商品实例,如果有相同属性的商品需要创建,则直接返回已有的实例,否则创建一个新的实例并添加到Map
中。
最后,我们来测试一下:
public class Client { public static void main(String[] args) { Product p1 = ProductFactory.getProduct("iphone13", 7999.0, "128GB", "iphone13.png"); Product p2 = ProductFactory.getProduct("iphone13", 7999.0, "128GB", "iphone13.png"); Product p3 = ProductFactory.getProduct("MacBook Pro", 9999.0, "16GB", "macbook-pro.png"); p1.showInfo(); p2.showInfo(); p3.showInfo(); System.out.println("p1 == p2:" + (p1 == p2)); // true } }
输出:
// 名称:iphone13 // 价格:7999.0 // 描述:128GB // 图片:iphone13.png // 名称:iphone13 // 价格:7999.0 // 描述:128GB // 图片:iphone13.png // 名称:MacBook Pro // 价格:9999.0 // 描述:16GB // 图片:macbook-pro.png // p1 == p2:true
享元模式
的优点包括:
- 节省内存空间:享元模式能够共享一些内部状态,从而减少对象的数量,节省内存空间。
- 提高性能:由于减少了对象的数量,也减少了对象的创建和销毁的开销,提高了系统的性能。
- 支持大量细粒度对象的复用:享元模式可以用于细粒度对象的复用,这些对象通常是由于数量庞大,造成系统的性能问题,通过享元模式,可以极大的减少对象的数量,提高系统的性能。
- 提高系统可扩展性:通过享元模式的拆分,可以分离内部状态和外部状态,从而提高系统的可扩展性。
总之,享元模式
能够在一定程度上提高系统的性能
和可扩展性
,特别适合处理大量细粒度对象的情况。
结束语
设计模式其实并不难,大家在学习的时候一定要在理解的基础上去写代码,不要去背代码。下节给大家讲代理模式
~
本着把自己知道的都告诉大家,如果本文对您有所帮助,点赞+关注
鼓励一下呗~
相关文章
- 一起来学设计模式之认识设计模式
- 一起来学设计模式之单例模式
- 一起来学设计模式之工厂模式
- 一起来学设计模式之建造者模式
- 一起来学设计模式之原型模式
- 一起来学设计模式之适配器模式
- 一起来学设计模式之桥接模式
- 一起来学设计模式之组合模式
- 一起来学设计模式之装饰器模式
- 一起来学设计模式之外观模式
项目源码(源码已更新 欢迎star⭐️)
Kafka 专题学习
- 一起来学kafka之Kafka集群搭建
- 一起来学kafka之整合SpringBoot基本使用
- 一起来学kafka之整合SpringBoot深入使用(一)
- 一起来学kafka之整合SpringBoot深入使用(二)
- 一起来学kafka之整合SpringBoot深入使用(三)
项目源码(源码已更新 欢迎star⭐️)
ElasticSearch 专题学习
- 利用docker搭建es集群
- 一起来学ElasticSearch(一)
- 一起来学ElasticSearch(二)
- 一起来学ElasticSearch(三)
- 一起来学ElasticSearch(四)
- 一起来学ElasticSearch(五)
- 一起来学ElasticSearch(六)
- 一起来学ElasticSearch(七)
- 一起来学ElasticSearch(八)
- 一起来学ElasticSearch(九)
- 一起来学ElasticSearch(十)
- 一起来学ElasticSearch之整合SpringBoot(一)
- 一起来学ElasticSearch之整合SpringBoot(二)
- 一起来学ElasticSearch之整合SpringBoot(三)
项目源码(源码已更新 欢迎star⭐️)
往期并发编程内容推荐
- Java多线程专题之线程与进程概述
- Java多线程专题之线程类和接口入门
- Java多线程专题之进阶学习Thread(含源码分析)
- Java多线程专题之Callable、Future与FutureTask(含源码分析)
- 面试官: 有了解过线程组和线程优先级吗
- 面试官: 说一下线程的生命周期过程
- 面试官: 说一下线程间的通信
- 面试官: 说一下Java的共享内存模型
- 面试官: 有了解过指令重排吗,什么是happens-before
- 面试官: 有了解过volatile关键字吗 说说看
- 面试官: 有了解过Synchronized吗 说说看
- Java多线程专题之Lock锁的使用
- 面试官: 有了解过ReentrantLock的底层实现吗?说说看
- 面试官: 有了解过CAS和原子操作吗?说说看
- Java多线程专题之线程池的基本使用
- 面试官: 有了解过线程池的工作原理吗?说说看
- 面试官: 线程池是如何做到线程复用的?有了解过吗,说说看
- 面试官: 阻塞队列有了解过吗?说说看
- 面试官: 阻塞队列的底层实现有了解过吗? 说说看
- 面试官: 同步容器和并发容器有用过吗? 说说看
- 面试官: CopyOnWrite容器有了解过吗? 说说看
- 面试官: Semaphore在项目中有使用过吗?说说看(源码剖析)
- 面试官: Exchanger在项目中有使用过吗?说说看(源码剖析)
- 面试官: CountDownLatch有了解过吗?说说看(源码剖析)
- 面试官: CyclicBarrier有了解过吗?说说看(源码剖析)
- 面试官: Phaser有了解过吗?说说看
- 面试官: Fork/Join 有了解过吗?说说看(含源码分析)
- 面试官: Stream并行流有了解过吗?说说看
推荐 SpringBoot & SpringCloud (源码已更新 欢迎star⭐️)
- springboot-all
地址
: github.com/qiuChenglei…- SpringBoot系列教程合集
- 一起来学SpringCloud合集
- SpringCloud整合 Oauth2+Gateway+Jwt+Nacos 实现授权码模式的服务认证(一)
- SpringCloud整合 Oauth2+Gateway+Jwt+Nacos 实现授权码模式的服务认证(二)