把书读薄 | 《设计模式之美》设计模式与范式(结构型-享元模式)(上)

简介: 本文对应设计模式与范式:结构型(54-55),享元模式 (Flyweight Pattern),结构型设计模式最后一个~

0x0、引言


🤡提测了等改BUG,摸鱼时啃下《设计模式之美》,本文对应设计模式与范式:结构型(54-55),享元模式 (Flyweight Pattern),结构型设计模式最后一个~


  • 很好理解 → 享元,被共享的单元


  • 意图 → 节省内存,复用不可变对象


  • 换句话说 → 找出相似对象间的共有特征,然后复用这些特征


一个形象的例子:游戏开发中,一个森林场景,成千上万种树,每棵树都实例化不同的模型,内存直接爆炸,可以抽取出所有树对象的共有属性,转移到一个单独的类中,然后只需要一个类实例,然后森林里的每一颗树对这个实例做一次引用(图摘自:Flyweight):


网络异常,图片无法展示
|


Tips:二手知识加工难免有所纰漏,感兴趣有时间的可自行查阅原文,谢谢。


0x1、写个简单的扑克牌例子


如果让你实现一个简单的扑克牌程序,代码可能是这样的(此处假定没有王,只有52张牌,4种花色):


// 牌类,有花色和大小两个属性
public class Card {
    private String color;
    private String num;
    public Card(String color, String num) {
        this.color = color;
        this.num = num;
    }
    public String printMsg() { return "扑克牌【" + color + num +"】"; }
}
// 测试用例
public class Player {
    public static void main(String[] args) {
        String[] colors = new String[]{"黑桃", "红心", "梅花", "方块"};
        List<Card> cards = new ArrayList<>();
        for (String color : colors) {
            for (int i = 1; i <= 13; i++) {
                switch (i) {
                    case 11: cards.add(new Card(color, "J")); break;
                    case 12: cards.add(new Card(color, "Q")); break;
                    case 13: cards.add(new Card(color, "K")); break;
                    default: cards.add(new Card(color, i + "")); break;
                }
            }
        }
        System.out.println("扑克牌初始完毕,共" + cards.size() + "张");
        System.out.println("随机派五张牌:");
        for (int i = 0; i < 5; i++) System.out.println(cards.get((int) (Math.random() * 52)).printMsg());
    }
}


运行输出结果如下


网络异常,图片无法展示
|


正常输出,但却初始化了52个Card对象,?如果用享元模式需要创建几个呢?


抽取下扑克牌的共有属性:花色和大小,花色固定四种,大小变化,写一个卡牌的父类,写四个花色子类继承:


// 享元类(抽象类或接口)
abstract class AbstractCard {
    // 共享对象需实现的公共操作方法,使用一个外部状态作为输入参数(客户端保存,运行时改变)
    abstract String printMsg(String num);
}
// 具体享元类
class SpadeCard extends AbstractCard {
    @Override String printMsg(String num) { return "黑桃" + num; }
}
class HeartCard extends AbstractCard {
    @Override String printMsg(String num) { return "红心" + num; }
}
class SpadeCard extends AbstractCard {
    @Override String printMsg(String num) { return "黑桃" + num; }
}
class DiamondCard extends AbstractCard {
    @Override String printMsg(String num) { return "方块" + num; }
}
// 享元工厂
public class PokerFactory {
    public static final int SPADE = 0;    // 黑桃
    public static final int HEART = 1;    // 红心
    public static final int CLUB = 2;     // 梅花
    public static final int DIAMOND = 3;  // 方块
    public static Map<Integer, AbstractCard> pokers = new HashMap<>();
    public static AbstractCard getPoker(int color) {
        // 直接拿,不用再调一次containsKey
        AbstractCard card = pokers.get(color);
        if(card == null) {
            System.out.println("花色对象不存在,新建对象...");
            switch (color) {
                case SPADE: card = new SpadeCard(); break;
                case HEART: card = new HeartCard(); break;
                case CLUB: card = new ClubCard(); break;
                default: card = new DiamondCard(); break;
            }
            pokers.put(color, card);
        } else {
            System.out.println("花色对象已存在,复用对象...");
        }
        return card;
    }
}
// 测试用例
public class Player {
    public static void main(String[] args) {
        for (int i = 0; i < 5; i++) {
            AbstractCard card;
            // 随机花色
            switch ((int) (Math.random() * 4)) {
                case 0: card = PokerFactory.getPoker(PokerFactory.SPADE); break;
                case 1: card = PokerFactory.getPoker(PokerFactory.HEART); break;
                case 2: card = PokerFactory.getPoker(PokerFactory.CLUB); break;
                default: card = PokerFactory.getPoker(PokerFactory.DIAMOND); break;
            }
            // 随机大小
            int num = (int)(Math.random() * 13 + 1);
            switch (num) {
                case 11: System.out.println(card.printMsg("J")); break;
                case 12: System.out.println(card.printMsg("Q")); break;
                case 13: System.out.println(card.printMsg("K")); break;
                default: System.out.println(card.printMsg(num + "")); break;
            }
        }
    }
}


相关文章
|
2月前
|
设计模式 存储 缓存
【设计模式】【结构型模式】享元模式(Flyweight)
一、入门 什么是享元模式? 享元模式(Flyweight Pattern)是一种结构型设计模式,旨在通过共享对象来减少内存使用,特别适用于存在大量相似对象的情况。 它的核心思想是将对象的内在状态(不变
108 16
|
2月前
|
设计模式 缓存 安全
【高薪程序员必看】万字长文拆解Java并发编程!(8):设计模式-享元模式设计指南
🌟 ​大家好,我是摘星!​ 🌟今天为大家带来的是并发编程中的经典对象复用设计模式-享元模式,废话不多说让我们直接开始。
63 0
|
5月前
|
设计模式 存储 缓存
「全网最细 + 实战源码案例」设计模式——享元模式
享元模式(Flyweight Pattern)是一种结构型设计模式,旨在减少大量相似对象的内存消耗。通过分离对象的内部状态(可共享、不变)和外部状态(依赖环境、变化),它有效减少了内存使用。适用于存在大量相似对象且需节省内存的场景。模式优点包括节省内存和提高性能,但会增加系统复杂性。实现时需将对象成员变量拆分为内在和外在状态,并通过工厂类管理享元对象。
224 92
|
10月前
|
设计模式 Java
Java设计模式-享元模式(12)
Java设计模式-享元模式(12)
112 1
|
11月前
|
设计模式 存储 Java
【十】设计模式~~~结构型模式~~~享元模式(Java)
文章详细介绍了享元模式(Flyweight Pattern),这是一种对象结构型模式,通过共享技术实现大量细粒度对象的重用,区分内部状态和外部状态来减少内存中对象的数量,提高系统性能。通过围棋棋子的设计案例,展示了享元模式的动机、定义、结构、优点、缺点以及适用场景,并探讨了单纯享元模式和复合享元模式以及与其他模式的联用。
【十】设计模式~~~结构型模式~~~享元模式(Java)
|
设计模式 存储 JavaScript
js设计模式【详解】—— 享元模式
js设计模式【详解】—— 享元模式
132 6
|
设计模式 缓存 Java
Java设计模式:享元模式实现高效对象共享与内存优化(十一)
Java设计模式:享元模式实现高效对象共享与内存优化(十一)
|
2月前
|
设计模式 Java 数据库连接
【设计模式】【创建型模式】工厂方法模式(Factory Methods)
一、入门 什么是工厂方法模式? 工厂方法模式(Factory Method Pattern)是一种创建型设计模式,它定义了一个用于创建对象的接口,但由子类决定实例化哪个类。工厂方法模式使类的实例化延迟
86 16
|
2月前
|
设计模式 负载均衡 监控
并发设计模式实战系列(2):领导者/追随者模式
🌟 ​大家好,我是摘星!​ 🌟今天为大家带来的是并发设计模式实战系列,第二章领导者/追随者(Leader/Followers)模式,废话不多说直接开始~
65 0
|
2月前
|
设计模式 监控 Java
并发设计模式实战系列(1):半同步/半异步模式
🌟 ​大家好,我是摘星!​ 🌟今天为大家带来的是并发设计模式实战系列,第一章半同步/半异步(Half-Sync/Half-Async)模式,废话不多说直接开始~
51 0

热门文章

最新文章