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

背景

假设我们有一个围棋游戏,棋盘上有很多棋子,每个棋子都有自己的位置和颜色。如果每个棋子都创建一个对象,那么内存占用会很大。而使用享元模式,我们可以共享相同颜色的棋子对象,只需记录它们的位置,从而减少内存占用。

概述

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

示例一

首先,我们创建一个棋子接口 ChessPiece,定义了棋子的共享属性和方法:

public interface ChessPiece {
    void setColor(String color);
    void setPosition(int x, int y);
    void display();
}

然后,我们创建两个具体的享元类,分别表示黑色棋子和白色棋子:

public class BlackChessPiece implements ChessPiece {
    private String color;
    private int x;
    private int y;
    
    public void setColor(String color) {
        this.color = color;
    }
    
    public void setPosition(int x, int y) {
        this.x = x;
        this.y = y;
    }
    
    public void display() {
        System.out.println("Displaying black chess piece at position (" + x + ", " + y + ")");
    }
}

public class WhiteChessPiece implements ChessPiece {
    private String color;
    private int x;
    private int y;
    
    public void setColor(String color) {
        this.color = color;
    }
    
    public void setPosition(int x, int y) {
        this.x = x;
        this.y = y;
    }
    
    public void display() {
        System.out.println("Displaying white chess piece at position (" + x + ", " + y + ")");
    }
}

接下来,我们创建一个享元工厂类 ChessPieceFactory,用于创建和管理棋子对象:

public class ChessPieceFactory {
    private static Map<String, ChessPiece> chessPieces = new HashMap<>();
    
    public static ChessPiece getChessPiece(String color) {
        ChessPiece chessPiece = chessPieces.get(color);
        
        if (chessPiece == null) {
            if (color.equals("black")) {
                chessPiece = new BlackChessPiece();
            } else if (color.equals("white")) {
                chessPiece = new WhiteChessPiece();
            }
            
            chessPieces.put(color, chessPiece);
        }
        
        return chessPiece;
    }
}

最后,我们可以在游戏中使用享元模式来创建和显示棋子:

public class Game {
    public static void main(String[] args) {
        ChessPiece blackChessPiece1 = ChessPieceFactory.getChessPiece("black");
        blackChessPiece1.setPosition(0, 0);
        blackChessPiece1.display();
        
        ChessPiece blackChessPiece2 = ChessPieceFactory.getChessPiece("black");
        blackChessPiece2.setPosition(1, 1);
        blackChessPiece2.display();
        
        ChessPiece whiteChessPiece1 = ChessPieceFactory.getChessPiece("white");
        whiteChessPiece1.setPosition(2, 2);
        whiteChessPiece1.display();
        
        ChessPiece whiteChessPiece2 = ChessPieceFactory.getChessPiece("white");
        whiteChessPiece2.setPosition(3, 3);
        whiteChessPiece2.display();
    }
}

输出结果

Displaying black chess piece at position (0, 0)
Displaying black chess piece at position (1, 1)
Displaying white chess piece at position (2, 2)
Displaying white chess piece at position (3, 3)

示例二

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

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

代码:

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<String, Mail> 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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值