【设计模式】用Java实现享元模式

简介: 享元模式(Flyweight Pattern)是一种结构型设计模式,旨在通过共享对象来最小化内存使用和提高性能。享元模式通过将对象的状态分为内部状态(Intrinsic State)和外部状态(Extrinsic State),并共享内部状态,从而在大量相似对象之间实现有效的资源共享

一.享元模式介绍与使用场景


享元模式(Flyweight Pattern)是一种结构型设计模式,旨在通过共享对象来最小化内存使用和提高性能。享元模式通过将对象的状态分为内部状态(Intrinsic State)和外部状态(Extrinsic State),并共享内部状态,从而在大量相似对象之间实现有效的资源共享。


内部状态是对象可共享的、独立于对象场景的状态,它可以被多个对象共享。外部状态是对象特定的、依赖于对象场景的状态,它不能被共享,每个对象都会保持一份独立的外部状态。


享元模式的关键思想是将对象的状态分离,并共享内部状态,而通过外部状态来区分和定制对象的行为。这样,在需要创建大量相似对象时,可以避免创建过多的对象,节省内存和系统资源。


应用场景:


1.当一个类需要创建大量相似的对象,且这些对象的区别仅在于它们的内部状态时。享元模式通过共享内部状态,减少了对象的数量,节省了内存和系统资源。

2.当对象的大部分状态可以被外部状态替代时,可以使用享元模式来共享内部状态,并将外部状态作为参数传递给享元对象。这样可以减少对象的数量,并且在使用时可以动态地改变外部状态,实现个性化的行为。

3.当需要频繁创建和销毁对象,且对象的创建和销毁操作消耗较大时,可以使用享元模式来重用已有对象,减少对象的创建和销毁次数,提高系统性能。

4.当系统中的多个对象共享相同的信息时,可以使用享元模式来将共享信息提取为共享对象,避免重复存储相同的数据,减少内存占用。


一些常见的应用场景包括:

文字处理器中的字符对象,可以使用享元模式来共享相同的字符对象,避免创建大量相同的字符对象。


图形界面中的图元对象,可以使用享元模式来共享相同的图元对象,提高图形渲染效率。


线程池中的线程对象,可以使用享元模式来共享线程对象,减少线程创建和销毁的开销。


缓存系统中的缓存对象,可以使用享元模式来共享相同的缓存对象,提高缓存命中率。

总之,享元模式适用于需要创建大量相似对象、可以共享内部状态、需要节省内存和系统资源的场景。它可以通过共享对象来提高系统性能,并且在一定程度上降低了对象的复杂性和内存消耗。


二.享元模式实现


下面是一个使用Java实现享元模式的简单示例:


首先,定义享元接口 Flyweight,它声明了一个操作方法 operate():

interface Flyweight {
    void operate(String extrinsicState);
}

然后,创建具体的享元类 ConcreteFlyweight,它实现了享元接口,并包含内部状态:

class ConcreteFlyweight implements Flyweight {
    private String intrinsicState;
    public ConcreteFlyweight(String intrinsicState) {
        this.intrinsicState = intrinsicState;
    }
    public void operate(String extrinsicState) {
        System.out.println("Intrinsic State: " + intrinsicState);
        System.out.println("Extrinsic State: " + extrinsicState);
        // 执行享元操作
    }
}

接下来,创建享元工厂类 FlyweightFactory,用于管理和共享享元对象:

import java.util.HashMap;
import java.util.Map;
class FlyweightFactory {
    private Map<String, Flyweight> flyweights;
    public FlyweightFactory() {
        flyweights = new HashMap<>();
    }
    public Flyweight getFlyweight(String intrinsicState) {
        if (flyweights.containsKey(intrinsicState)) {
            return flyweights.get(intrinsicState);
        } else {
            Flyweight flyweight = new ConcreteFlyweight(intrinsicState);
            flyweights.put(intrinsicState, flyweight);
            return flyweight;
        }
    }
}

最后,我们可以在客户端中使用享元工厂类来获取和使用享元对象:

public class Client {
    public static void main(String[] args) {
        FlyweightFactory factory = new FlyweightFactory();
        // 获取或创建享元对象
        Flyweight flyweight1 = factory.getFlyweight("SharedState");
        Flyweight flyweight2 = factory.getFlyweight("SharedState");
        // 使用享元对象
        flyweight1.operate("ExtrinsicState1");
        flyweight2.operate("ExtrinsicState2");
    }
}

输出结果为:

Intrinsic State: SharedState
Extrinsic State: ExtrinsicState1
Intrinsic State: SharedState
Extrinsic State: ExtrinsicState2

通过享元模式,我们可以共享具有相同内部状态的对象,避免创建过多的对象实例,从而节省内存和系统资源。在实际项目中,享元模式常用于需要创建大量相似对象的场景,例如线程池、缓存、文字处理器等。


需要注意的是,享元模式在共享对象时需要确保对象的内部状态是不可变的,以避免状态被修改造成共享对象的不一致性。


下面再举一个在实际项目中模拟一个文字处理器的字符对象共享的例子。


首先,定义享元接口 Character,它声明了一个方法 display():

interface Character {
    void display();
}

然后,创建具体的享元类 ConcreteCharacter,它实现了享元接口,并包含内部状态:

class ConcreteCharacter implements Character {
    private char symbol;
    public ConcreteCharacter(char symbol) {
        this.symbol = symbol;
    }
    public void display() {
        System.out.println("Character: " + symbol);
    }
}

接下来,创建享元工厂类 CharacterFactory,用于管理和共享字符对象:

import java.util.HashMap;
import java.util.Map;
class CharacterFactory {
    private Map<Character, Character> characters;
    public CharacterFactory() {
        characters = new HashMap<>();
    }
    public Character getCharacter(char symbol) {
        if (characters.containsKey(symbol)) {
            return characters.get(symbol);
        } else {
            Character character = new ConcreteCharacter(symbol);
            characters.put(symbol, character);
            return character;
        }
    }
}

最后,我们可以在客户端中使用享元工厂类来获取和使用字符对象:

public class Client {
    public static void main(String[] args) {
        CharacterFactory factory = new CharacterFactory();
        // 获取或创建字符对象
        Character character1 = factory.getCharacter('A');
        Character character2 = factory.getCharacter('B');
        Character character3 = factory.getCharacter('A');
        // 使用字符对象
        character1.display(); // 输出:Character: A
        character2.display(); // 输出:Character: B
        character3.display(); // 输出:Character: A
        System.out.println(character1 == character3); // 输出:true,字符对象被共享
    }
}

输出结果为:

Character: A
Character: B
Character: A
true

通过享元模式,我们可以共享具有相同内部状态的字符对象,避免创建多个相同的字符对象,节省了内存和系统资源。在实际项目中,享元模式可以应用于文字处理器、图形渲染器等需要大量相似对象的场景,从而提高系统性能和资源利用率。


需要注意的是,在享元模式中,内部状态应该是不可变的,以确保共享对象的一致性。如果需要修改内部状态,应该通过外部状态来实现个性化的行为。


相关文章
|
4月前
|
设计模式 存储 缓存
【设计模式】【结构型模式】享元模式(Flyweight)
一、入门 什么是享元模式? 享元模式(Flyweight Pattern)是一种结构型设计模式,旨在通过共享对象来减少内存使用,特别适用于存在大量相似对象的情况。 它的核心思想是将对象的内在状态(不变
177 16
|
4月前
|
设计模式 缓存 安全
【高薪程序员必看】万字长文拆解Java并发编程!(8):设计模式-享元模式设计指南
🌟 ​大家好,我是摘星!​ 🌟今天为大家带来的是并发编程中的经典对象复用设计模式-享元模式,废话不多说让我们直接开始。
105 0
|
7月前
|
设计模式 存储 缓存
「全网最细 + 实战源码案例」设计模式——享元模式
享元模式(Flyweight Pattern)是一种结构型设计模式,旨在减少大量相似对象的内存消耗。通过分离对象的内部状态(可共享、不变)和外部状态(依赖环境、变化),它有效减少了内存使用。适用于存在大量相似对象且需节省内存的场景。模式优点包括节省内存和提高性能,但会增加系统复杂性。实现时需将对象成员变量拆分为内在和外在状态,并通过工厂类管理享元对象。
251 92
|
6月前
|
设计模式 Java 数据安全/隐私保护
Java 设计模式:装饰者模式(Decorator Pattern)
装饰者模式属于结构型设计模式,允许通过动态包装对象的方式为对象添加新功能,提供比继承更灵活的扩展方式。该模式通过组合替代继承,遵循开闭原则(对扩展开放,对修改关闭)。
|
10月前
|
设计模式 消息中间件 搜索推荐
Java 设计模式——观察者模式:从优衣库不使用新疆棉事件看系统的动态响应
【11月更文挑战第17天】观察者模式是一种行为设计模式,定义了一对多的依赖关系,使多个观察者对象能直接监听并响应某一主题对象的状态变化。本文介绍了观察者模式的基本概念、商业系统中的应用实例,如优衣库事件中各相关方的动态响应,以及模式的优势和实际系统设计中的应用建议,包括事件驱动架构和消息队列的使用。
168 6
|
10月前
|
设计模式 Java 数据库连接
Java编程中的设计模式:单例模式的深度剖析
【10月更文挑战第41天】本文深入探讨了Java中广泛使用的单例设计模式,旨在通过简明扼要的语言和实际示例,帮助读者理解其核心原理和应用。文章将介绍单例模式的重要性、实现方式以及在实际应用中如何优雅地处理多线程问题。
139 4
|
10月前
|
设计模式 JavaScript Java
Java设计模式:建造者模式详解
建造者模式是一种创建型设计模式,通过将复杂对象的构建过程与表示分离,使得相同的构建过程可以创建不同的表示。本文详细介绍了建造者模式的原理、背景、应用场景及实际Demo,帮助读者更好地理解和应用这一模式。
459 0
|
4月前
|
设计模式 Java 数据库连接
【设计模式】【创建型模式】工厂方法模式(Factory Methods)
一、入门 什么是工厂方法模式? 工厂方法模式(Factory Method Pattern)是一种创建型设计模式,它定义了一个用于创建对象的接口,但由子类决定实例化哪个类。工厂方法模式使类的实例化延迟
131 16
|
4月前
|
设计模式 负载均衡 监控
并发设计模式实战系列(2):领导者/追随者模式
🌟 ​大家好,我是摘星!​ 🌟今天为大家带来的是并发设计模式实战系列,第二章领导者/追随者(Leader/Followers)模式,废话不多说直接开始~
128 0