需求
扑克牌
问题,这里要创建 52
个 Card
对象,但这里花色只有四种是固定的,不同的是大小,可以用享元模式来共享对象,减少内存消耗。
什么是享元模式
“享” 是共享的意思,“元” 指的是元件,也就是小颗粒的东西,享元顾名思义便是共享小部件,很多系统或者程序包含大量对象,但是这些对象绝大多数都是差不多的,除了一些极个别的属性外。当一个软件系统在运行时产生的对象数量太多,将导致运行代价过高,带来系统性能下降等问题。享元模式正为解决这一类问题而诞生。享元模式以共享的方式高效地支持大量细粒度对象的重用,在享元模式中,存储这些共享实例对象的地方称为享元池(Flyweight Pool)
代码实现
抽象类
/**
* @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 + "]");
}
}
具体实现
/**
* @author BNTang
* @program design-pattern-pro
* @date Created in 2021/10/09 009 15:42
* @description
**/
public class SpadeCard extends AbstractCard {
public String getColor() {
return "黑桃♠️";
}
}
/**
* @author BNTang
* @program design-pattern-pro
* @date Created in 2021/10/09 009 15:49
* @description
**/
public class HeartCard extends AbstractCard {
public String getColor() {
return "红桃♥";
}
}
/**
* @author BNTang
* @program design-pattern-pro
* @date Created in 2021/10/09 009 15:50
* @description
**/
public class ClubsCard extends AbstractCard{
public String getColor() {
return "草花";
}
}
/**
* @author BNTang
* @program design-pattern-pro
* @date Created in 2021/10/09 009 15:50
* @description
**/
public class DiamondsCard extends AbstractCard{
public String getColor() {
return "方块";
}
}
工厂类
/**
* @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;
}
}
}
客户端使用
/**
* @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;
}
}
});
}
}
运行结果如下:
角色
抽象享元角色(Flyweight)
是所有的具体享元类的基类,为具体享元规范需要实现的公共接口,非享元的外部状态以参数的形式通过方法传入。
具体享元(Concrete Flyweight)角色
实现抽象享元角色中所规定的接口。
非享元(Unsharable Flyweight)角色
是不可以共享的外部状态,它以参数的形式注入具体享元的相关方法中。
享元工厂(Flyweight Factory)角色
负责创建和管理享元角色。当客户对象请求一个享元对象时,享元工厂检査系统中是否存在符合要求的享元对象,如果存在则提供给客户。如果不存在的话,则创建一个新的享元对象。
UML 图
优缺点
优点,相同对象只要保存一份,这降低了系统中对象的数量,从而降低了系统中细粒度对象给内存带来的压力。缺点,为了使对象可以共享,需要将一些不能共享的状态外部化,这将增加程序的复杂性。读取享元模式的外部状态会使得运行时间稍微变长。
源码
- Interge.valueOf
- String