Java设计模式-享元模式(12)

简介: Java设计模式-享元模式(12)

大家好,我是馆长!今天开始我们讲的是结构型模式中的享元模式。老规矩,讲解之前再次熟悉下结构型模式包含:代理模式、适配器模式、桥接模式、装饰器模式、外观模式、享元模式、组合模式,共7种设计模式。

享元模式(Flyweight Pattern)

定义

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

解决问题

创建大量相同或相似对象实例的问题。创建那么多的对象将会耗费很多的系统资源,它是系统性能提高的一个瓶颈,在有大量对象时,有可能会造成内存溢出,如果把它们相同的部分提取出来共享,则能节省大量的系统资源,我们把其中共同的部分抽象出来,如果有相同的业务请求,直接返回在内存中已有的对象,避免重新创建。

实现

内部状态:即不会随着环境的改变而改变的可共享部分。

外部状态:指随环境改变而改变的不可以共享的部分。

享元模式的实现要领就是区分应用中的这两种状态,并将外部状态外部化。下面来分析其基本结构和实现方法。

结构

主要角色:

抽象享元角色(Flyweight):是所有的具体享元类的基类,为具体享元规范需要实现的公共接口,非享元的外部状态以参数的形式通过方法传入。

具体享元(Concrete Flyweight)角色:实现抽象享元角色中所规定的接口。

非享元(Unsharable Flyweight)角色:是不可以共享的外部状态,它以参数的形式注入具体享元的相关方法中。

享元工厂(Flyweight Factory)角色:负责创建和管理享元角色。当客户对象请求一个享元对象时,享元工厂检查系统中是否存在符合要求的享元对象,如果存在则提供给客户;如果不存在的话,则创建一个新的享元对象。

应用场景:

系统中存在大量相同或相似的对象,这些对象耗费大量的内存资源。

大部分的对象可以按照内部状态进行分组,且可将不同部分外部化,这样每一个组只需保存一个内部状态【数据分离形态】。

需要缓冲池的场景。

注意:

注意划分外部状态和内部状态,否则可能会引起线程安全问题。

这些类必须有一个工厂对象加以控制,控制对象的维护和获取,以及其他的业务设定。

由于享元模式需要额外维护一个保存享元的数据结构,所以应当在有足够多的享元实例时才值得使用享元模式。

优点:

相同对象只要保存一份,这降低了系统中对象的数量,从而降低了系统中细粒度对象给内存带来的压力。

大大减少对象的创建,降低系统的内存,使效率提高。

缺点:

为了使对象可以共享,需要将一些不能共享的状态外部化,这将增加程序的复杂性。

读取享元模式的外部状态会使得运行时间稍微变长。

代码实现:模拟在坐标系中绘制图形。

//抽象享元角色:Marker
public interface Maker {
void draw(Coordinate coordinate);
}
​​​​​​
//具体享元角色: CircleMaker
@Data
public class CircleMaker implements Maker {

@Override
public void draw(Coordinate coordinate) {
System.out.println("在X:"+coordinate.getX()+"Y:"+coordinate.getY()+"为圆点,绘制圆形");
}
}
​​​​​
//具体享元角色: RectangleMaker
@Data
public class RectangleMaker implements Maker {

@Override
public void draw(Coordinate coordinate) {
System.out.println("在X:"+coordinate.getX()+"Y:"+coordinate.getY()+"为中心点,绘制矩形");
}
}
​​​​​​​
//非享元角色:Coordinate
@Data
public class Coordinate {
private Double x;
private Double y;

Coordinate() {
}

Coordinate(Double x, Double y) {
this.x = x;
this.y = y;
}
}

​​​​​​​

//限定获取结构:只能获取这些类型
public enum MakerType {
Circle("CircleMaker"),Rectangle("RectangleMaker");

private String name;
MakerType(String name){
this.name=name;
}
}

​​
//享元工厂角色:MakerFactory
@Data
public class MakerFactory {
private Map pool = new HashMap();

//初始化
public static MakerFactory builder() {
return new MakerFactory();

}

private MakerFactory() {
}

public Maker get(MakerType type) {
if (pool.get(type) == null) {
System.out.println(type.name()+"被创建了");
switch (type) {
case Circle:
set(type, new CircleMaker());
break;
case Rectangle:
set(type, new RectangleMaker());
break;
default:
}
}else{
System.out.println(type.name()+"已创建,无需创建");
}

return pool.get(type);

}

private void set(MakerType type, Maker maker) {
pool.put(type, maker);
}
}

​​​​​
//模拟客户端:ClientDemo
public class ClientDemo {
public static void main(String[] args) {
MakerFactory makerFactory = MakerFactory.builder();
Maker c1 = makerFactory.get(MakerType.Circle);
c1.draw(new Coordinate(1.0, 3.0));
System.out.println("\n");

Maker c2 = makerFactory.get(MakerType.Circle);
c2.draw(new Coordinate(2.0, 4.0));
System.out.println("\n");

Maker r1 = makerFactory.get(MakerType.Rectangle);
r1.draw(new Coordinate(10.0, 30.0));
System.out.println("\n");

Maker r2 = makerFactory.get(MakerType.Rectangle);
r2.draw(new Coordinate(120.0, 130.0));

}
}

扩展

在实际使用过程中,有时候会稍加改变,即存在两种特殊的享元模式:单纯享元模式和复合享元模式:
(1)单纯享元模式:这种享元模式中的所有的具体享元类都是可以共享的,不存在非共享的具体享元类。

(2)复合享元模式:这种享元模式中的有些享元对象是由一些单纯享元对象组合而成的,它们就是复合享元对象。虽然复合享元对象本身不能共享,但它们可以分解成单纯享元对象再被共享。

好了,关于享元模式的说明,馆长就先讲到这里。谢谢各位看官!!

23 种设计模式不是孤立存在的,很多模式之间存在一定的关联关系,在大的系统开发中常常同时使用多种设计模式,或者模式与模式之间的组合进行生成更加强大的程序功能。

相关文章
|
1月前
|
设计模式 算法 Java
Java中的设计模式:提升代码质量的秘诀
【8月更文挑战第23天】在Java开发中,设计模式是提高代码可读性、可维护性和扩展性的强有力工具。本文通过浅显易懂的语言和实际案例,探讨几种常见的设计模式及其在Java中的应用,旨在帮助开发者更好地理解并运用这些模式来优化自己的代码结构。
46 2
|
13天前
|
设计模式 Java 关系型数据库
【Java笔记+踩坑汇总】Java基础+JavaWeb+SSM+SpringBoot+SpringCloud+瑞吉外卖/谷粒商城/学成在线+设计模式+面试题汇总+性能调优/架构设计+源码解析
本文是“Java学习路线”专栏的导航文章,目标是为Java初学者和初中高级工程师提供一套完整的Java学习路线。
155 37
|
9天前
|
设计模式 Java
Java设计模式:组合模式的介绍及代码演示
组合模式是一种结构型设计模式,用于将多个对象组织成树形结构,并统一处理所有对象。例如,统计公司总人数时,可先统计各部门人数再求和。该模式包括一个通用接口、表示节点的类及其实现类。通过树形结构和节点的通用方法,组合模式使程序更易扩展和维护。
Java设计模式:组合模式的介绍及代码演示
|
13天前
|
设计模式 安全 算法
【Java面试题汇总】设计模式篇(2023版)
谈谈你对设计模式的理解、七大原则、单例模式、工厂模式、代理模式、模板模式、观察者模式、JDK中用到的设计模式、Spring中用到的设计模式
【Java面试题汇总】设计模式篇(2023版)
|
13天前
|
设计模式 Java 关系型数据库
【Java笔记+踩坑】设计模式——原型模式
对比原型模式和传统方式的实现思路、代码方案、优缺点,阐述原型模式的使用场景,以及深拷贝、浅拷贝等相关概念,并扩展原型模式在Spring源码中的应用。
【Java笔记+踩坑】设计模式——原型模式
|
4天前
|
设计模式 安全 Java
Java 编程中的设计模式:单例模式的深度解析
【9月更文挑战第22天】在Java的世界里,单例模式就像是一位老练的舞者,轻盈地穿梭在对象创建的舞台上。它确保了一个类仅有一个实例,并提供全局访问点。这不仅仅是代码优雅的体现,更是资源管理的高手。我们将一起探索单例模式的奥秘,从基础实现到高级应用,再到它与现代Java版本的舞蹈,让我们揭开单例模式的面纱,一探究竟。
22 11
|
28天前
|
设计模式 缓存 算法
揭秘策略模式:如何用Java设计模式轻松切换算法?
【8月更文挑战第30天】设计模式是解决软件开发中特定问题的可重用方案。其中,策略模式是一种常用的行为型模式,允许在运行时选择算法行为。它通过定义一系列可互换的算法来封装具体的实现,使算法的变化与客户端分离。例如,在电商系统中,可以通过定义 `DiscountStrategy` 接口和多种折扣策略类(如 `FidelityDiscount`、`BulkDiscount` 和 `NoDiscount`),在运行时动态切换不同的折扣逻辑。这样,`ShoppingCart` 类无需关心具体折扣计算细节,只需设置不同的策略即可实现灵活的价格计算,符合开闭原则并提高代码的可维护性和扩展性。
39 2
|
28天前
|
设计模式 Java
Java 设计模式之谜:工厂模式与抽象工厂模式究竟隐藏着怎样的神奇力量?
【8月更文挑战第30天】在Java编程中,设计模式为常见问题提供了高效解决方案。工厂模式与抽象工厂模式是常用的对象创建型设计模式,能显著提升代码的灵活性、可维护性和可扩展性。工厂模式通过定义创建对象的接口让子类决定实例化哪个类;而抽象工厂模式则进一步提供了一个创建一系列相关或相互依赖对象的接口,无需指定具体类。这种方式使得系统更易于扩展和维护。
31 1
|
28天前
|
设计模式 Java
重构你的代码:探索Java中的混合、装饰器与组合设计模式
【8月更文挑战第30天】在软件开发中,设计模式为特定问题提供了结构化的解决方案,使代码更易理解、维护及扩展。本文将介绍三种常用的 Java 设计模式:混合模式、装饰器模式与组合模式,并附有示例代码展示实际应用。混合模式允许通过继承多个接口或抽象类实现多重继承;装饰器模式可在不改变对象结构的情况下动态添加新功能;组合模式则通过树形结构表示部分-整体层次,确保客户端处理单个对象与组合对象时具有一致性。
18 1
|
1月前
|
设计模式 算法 安全
Java编程中的设计模式:提升代码的可维护性和扩展性
【8月更文挑战第19天】在软件开发的世界里,设计模式是解决常见问题的一种优雅方式。本文将深入探讨Java编程语言中常用的几种设计模式,并解释如何通过这些模式来提高代码的可维护性和扩展性。文章不涉及具体的代码实现,而是侧重于理论和实践相结合的方式,为读者提供一种思考和改善现有项目的新视角。