【设计模式|结构型】享元模式(Flyweight Pattern)

概述

享元模式(Flyweight Pattern)是一种结构型设计模式,它旨在通过共享对象来减少系统中的对象数量,以便在有限的内存中节省空间和提高性能。在享元模式中,对象分为两部分:内部状态(Intrinsic State)和外部状态(Extrinsic State)。内部状态是固定且可共享的,它存储在享元对象内部。外部状态是变化的且不可共享的,它由客户端传入,并存储在客户端中。通过共享内部状态和外部状态,可以减少对象的创建和销毁,并通过共享来节省内存。

优点:

  1. 节省内存:通过共享内部状态,减少了对象的创建和销毁,节省了内存空间。
  2. 提高性能:共享对象可以减少系统中的对象数量,从而提高了系统的性能。
  3. 灵活性增加:通过将外部状态从对象中分离,使得对象可以共享内部状态的同时,根据外部状态的不同表现出不同的行为。

缺点:

  1. 对象共享可能导致线程安全问题:当多个线程同时访问共享对象时,需要考虑线程安全性,确保不会出现数据竞争的情况。

使用场景:

  1. 当应用程序中存在大量相似对象,并且这些对象可以共享其内部状态时,可以考虑使用享元模式。例如,文本编辑器中的字符对象可以通过共享相同的字体和大小来减少内存占用。
  2. 当需要缓存对象以提高系统性能时,可以考虑使用享元模式。例如,数据库连接池可以缓存数据库连接对象,以避免频繁创建和销毁连接。

示例

假设我们开发了一个电子邮件系统,需要创建大量的邮件对象。邮件对象包含标题、内容、发件人、收件人等属性。在传统的方式中,每个邮件对象都是独立创建和管理的,这将导致大量的内存占用和性能下降。

使用享元模式,我们可以将邮件对象中的一些内部属性,例如标题、内容等,作为内部状态,并且可以共享它们。外部状态,例如发件人、收件人等,由客户端传入并存储在客户端中。

代码:

import java.util.HashMap;
import java.util.Map;

// 邮件对象接口
interface Mail {
    void send();
}

// 具体邮件对象
class ConcreteMail implements Mail {
    private String title;
    private String content;

    public ConcreteMail(String title, String content) {
        this.title = title;
        this.content = content;
    }

    public void send() {
        System.out.println("发送邮件:标题:" + title + ",内容:" + content);
    }
}

// 邮件工厂类
class MailFactory {
    private Map mailCache;

    public MailFactory() {
        mailCache = new HashMap<>();
    }

    public Mail getMail(String title, String content) {
        String key = title + content;
        if (!mailCache.containsKey(key)) {
            mailCache.put(key, new ConcreteMail(title, content));
        }
        return mailCache.get(key);
    }
}

// 客户端代码
public class FlyweightExample {
    public static void main(String[] args) {
        MailFactory mailFactory = new MailFactory();

        // 创建多个邮件对象
        Mail mail1 = mailFactory.getMail("标题1", "内容1");
        Mail mail2 = mailFactory.getMail("标题2", "内容1");
        Mail mail3 = mailFactory.getMail("标题1", "内容1");

        // 发送邮件
        mail1.send(); // 发送邮件:标题:标题1,内容:内容1
        mail2.send(); // 发送邮件:标题:标题2,内容:内容1
        mail3.send(); // 发送邮件:标题:标题1,内容:内容1
    }
}

运行结果:

发送邮件:标题:标题1,内容:内容1
发送邮件:标题:标题2,内容:内容1
发送邮件:标题:标题1,内容:内容1

你可能感兴趣的:(探索设计模式,享元模式,设计模式)