享元模式

需求

扑克牌

image-20210926145508680

image-20210926145541303

问题,这里要创建 52Card 对象,但这里花色只有四种是固定的,不同的是大小,可以用享元模式来共享对象,减少内存消耗。

什么是享元模式

“享” 是共享的意思,“元” 指的是元件,也就是小颗粒的东西,享元顾名思义便是共享小部件,很多系统或者程序包含大量对象,但是这些对象绝大多数都是差不多的,除了一些极个别的属性外。当一个软件系统在运行时产生的对象数量太多,将导致运行代价过高,带来系统性能下降等问题。享元模式正为解决这一类问题而诞生。享元模式以共享的方式高效地支持大量细粒度对象的重用,在享元模式中,存储这些共享实例对象的地方称为享元池(Flyweight Pool)

代码实现

抽象类

image-20210926150120966

/**
 * @author BNTang
 * @program design-pattern-pro
 * @date Created in 2021/10/09 009 15:27
 * @description
 **/
public abstract class AbstractCard {
    /**
     * 得到颜色
     *
     * @return {@link String}
     */
    public abstract String getColor();

    /**
     * 展示牌
     *
     * @param num 牌数
     */
    public void showCards(String num) {
        System.out.println("Card[牌色=" + getColor() + ",牌数=" + num + "]");
    }
}

具体实现

image-20210926150231179

/**
 * @author BNTang
 * @program design-pattern-pro
 * @date Created in 2021/10/09 009 15:42
 * @description
 **/
public class SpadeCard extends AbstractCard {
    @Override
    public String getColor() {
        return "黑桃♠️";
    }
}

image-20210926150247223

/**
 * @author BNTang
 * @program design-pattern-pro
 * @date Created in 2021/10/09 009 15:49
 * @description
 **/
public class HeartCard extends AbstractCard {
    @Override
    public String getColor() {
        return "红桃♥";
    }
}

image-20210926150302314

/**
 * @author BNTang
 * @program design-pattern-pro
 * @date Created in 2021/10/09 009 15:50
 * @description
 **/
public class ClubsCard  extends AbstractCard{
    @Override
    public String getColor() {
        return "草花";
    }
}

image-20210926150320967

/**
 * @author BNTang
 * @program design-pattern-pro
 * @date Created in 2021/10/09 009 15:50
 * @description
 **/
public class DiamondsCard extends AbstractCard{
    @Override
    public String getColor() {
        return "方块";
    }
}

工厂类

image-20210926150416722

/**
 * @author BNTang
 * @program design-pattern-pro
 * @date Created in 2021/10/09 009 15:51
 * @description
 **/
public class CardFactory {
    public static final int SPADE = 1;
    public static final int CLUB = 2;
    public static final int HEARTS = 3;
    public static final int DIAMONDS = 4;
    private static final Map<Integer, AbstractCard> CARD_MAP = new HashMap<>();
    private static final CardFactory INSTANCE = new CardFactory();

    private CardFactory() {
    }

    public static CardFactory getInstance() {
        return INSTANCE;
    }

    public AbstractCard getCard(Integer color) {
        if (CARD_MAP.containsKey(color)) {
            System.out.println("复用对象");
            return CARD_MAP.get(color);
        } else {
            System.out.println("新建对象");
            AbstractCard card;
            switch (color) {
                case SPADE:
                    card = new SpadeCard();
                    break;
                case CLUB:
                    card = new ClubsCard();
                    break;
                case HEARTS:
                    card = new HeartCard();
                    break;
                default:
                    card = new DiamondsCard();
                    break;
            }
            CARD_MAP.put(color, card);
            return card;
        }
    }
}

客户端使用

image-20210926150453061

/**
 * @author BNTang
 * @program design-pattern-pro
 * @date Created in 2021/10/09 009 16:00
 * @description
 **/
public class Client {
    public static void main(String[] args) {
        CardFactory cardFactory = CardFactory.getInstance();
        IntStream.rangeClosed(0, 10).forEach(i -> {
            AbstractCard card = null;
            // 随机花色
            switch ((int) (Math.random() * 4)) {
                case 0:
                    card = cardFactory.getCard(CardFactory.SPADE);
                    break;
                case 1:
                    card = cardFactory.getCard(CardFactory.CLUB);
                    break;
                case 2:
                    card = cardFactory.getCard(CardFactory.HEARTS);
                    break;
                case 3:
                    card = cardFactory.getCard(CardFactory.DIAMONDS);
                    break;
            }

            // 随机大小
            if (null != card) {
                int num = (int) (Math.random() * 13) + 1;
                switch (num) {
                    case 11:
                        card.showCards("J");
                        break;
                    case 12:
                        card.showCards("Q");
                        break;
                    case 13:
                        card.showCards("K");
                        break;
                    default:
                        card.showCards(String.valueOf(num));
                        break;
                }
            }
        });
    }
}

运行结果如下:

image-20211010145521076

角色

抽象享元角色(Flyweight)

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

具体享元(Concrete Flyweight)角色

实现抽象享元角色中所规定的接口。

非享元(Unsharable Flyweight)角色

是不可以共享的外部状态,它以参数的形式注入具体享元的相关方法中。

享元工厂(Flyweight Factory)角色

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

UML 图

image-20211010162108586

image-20211010162126101

优缺点

优点,相同对象只要保存一份,这降低了系统中对象的数量,从而降低了系统中细粒度对象给内存带来的压力。缺点,为了使对象可以共享,需要将一些不能共享的状态外部化,这将增加程序的复杂性。读取享元模式的外部状态会使得运行时间稍微变长。

源码

  • Interge.valueOf
  • String
posted @ 2021-09-26 10:50  BNTang  阅读(575)  评论(0编辑  收藏  举报