image
抽象卡牌类:
public abstract class Card {
public abstract void showCards(String num);
具体卡牌类:
public class SpadeCard extends Card {
private String color = "黑桃";
public void showCards(String num) {
System.out.println("Card[牌色=" + color + ",牌数=" + num + "]");
}
}
public class ClubCard extends Card {
private String color = "草花";
public void showCards(String num) {
System.out.println("Card[牌色=" + color + ",牌数=" + num + "]");
}
}
public class HeartsCard extends Card {
private String color = "红桃";
public void showCards(String num) {
System.out.println("Card[牌色=" + color + ",牌数=" + num + "]");
}
}
public class DiamondsCard extends Card {
private String color = "方块";
public void showCards(String num) {
System.out.println("Card[牌色=" + color + ",牌数=" + num + "]");
}
}
享元工厂:
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 Map<Integer, Card> cards = new ConcurrentHashMap<Integer, Card>();
private static CardFactory instance = new CardFactory();
private CardFactory(){}
public static CardFactory getInstance(){
return instance;
}
public Card getCard(Integer color){
if (cards.containsKey(color)){
System.out.println("复用对象");
return cards.get(color);
}else {
System.out.println("新建对象");
Card card;
switch (color){
case SPADE: card = new SpadeCard();break;
case CLUB: card = new ClubCard();break;
case HEARTS:card = new HeartsCard();break;
default:card = new DiamondsCard();break;
}
cards.put(color, card);
return card;
}
}
}
测试随机发10张:
public class Game {
public static void main(String[] args) {
CardFactory factory = CardFactory.getInstance();
for (int i=0; i<10; i++ ){
Card card = null;
结果是:
新建对象
Card[牌色=方块,牌数=2]
新建对象
Card[牌色=红桃,牌数=6]
复用对象
Card[牌色=红桃,牌数=6]
新建对象
Card[牌色=草花,牌数=3]
复用对象
Card[牌色=方块,牌数=K]
新建对象
Card[牌色=黑桃,牌数=7]
复用对象
Card[牌色=黑桃,牌数=2]
复用对象
Card[牌色=黑桃,牌数=6]
复用对象
Card[牌色=方块,牌数=J]
复用对象
Card[牌色=红桃,牌数=7]
这里有拿到相同的花色和大小,因为这里的random并没有去重复,不是很严谨,只是为了举例说明。
六、单纯享元模式和复合享元模式
标准的享元模式结构图中既包含可以共享的具体享元类,也包含不可以共享的非共享具体享元类(不共享的一半直接实例化即可)。但是在实际使用过程中,我们有时候会用到两种特殊的享元模式:单纯享元模式和复合享元模式。
6.1、单纯享元模式
在单纯享元模式中,所有的具体享元类都是可以共享的,不存在非共享具体享元类。它的UML类图如下:
image
6.2、复合享元模式
在单纯享元模式中,所有的享元对象都是单纯享元对象,也就是说都是可以直接共享的。而还有一种较为复杂的情况,将一些单纯享元使用合成模式加以复合,形成复合享元对象。这样的复合享元对象本身不能共享,但是它们可以分解成单纯享元对象,而后者则可以共享。它的UML类图如下:
image
通过复合享元模式,可以确保复合享元类CompositeConcreteFlyweight中所包含的每个单纯享元类ConcreteFlyweight都具有相同的外部状态,而这些单纯享元的内部状态往往可以不同。如果希望为多个内部状态不同的享元对象设置相同的外部状态,可以考虑使用复合享元模式。
这时的享元工厂一半有两个方法,一种用于提供单纯享元对象,另一种用于提供复合享元对象。
public class CompositeConcreteFlyweight implements Flyweight {
private List<Flyweight> flyweights = new ArrayList<Flyweight>();
public void add(Flyweight flyweight){
flyweights.add(flyweight);
}
public void remove(Flyweight flyweight){
flyweights.remove(flyweight);
}
public void operation(String extrinsicState) {
for (Flyweight flyweight : flyweights){
flyweight.operation(extrinsicState);
}
}
}
public class FlyweightFactory {
七、模式扩展
享元模式通常需要和其他模式一起联用,几种常见的联用方式如下:
- 在享元模式的享元工厂类中通常提供一个静态的工厂方法用于返回享元对象,使用简单工厂模式来生成享元对象。
- 在一个系统中,通常只有唯一一个享元工厂,因此可以使用单例模式进行享元工厂类的设计。
- 享元模式可以结合组合模式形成复合享元模式,统一对多个享元对象设置外部状态。
八、优点和缺点
8.1、优点
享元模式的主要优点如下:
- 可以极大减少内存中对象的数量,使得相同或相似对象在内存中只保存一份,从而可以节约系统资源,提高系统性能。
- 享元模式的外部状态相对独立,而且不会影响其内部状态,从而使得享元对象可以在不同的环境中被共享。
8.2、缺点
享元模式的主要缺点如下:
- 享元模式使得系统变得复杂,需要分离出内部状态和外部状态,这使得程序的逻辑复杂化。
- 为了使对象可以共享,享元模式需要将享元对象的部分状态外部化,而读取外部状态将使得运行时间变长。
九、适用环境
享元模式的使用频率并不算太高,但是作为一种以“节约内存,提高性能”为出发点的设计模式,它在软件开发中还是得到了一定程度的应用。
在以下情况下可以考虑使用享元模式:
- 一个系统有大量相同或者相似的对象,造成内存的大量耗费。
- 对象的大部分状态都可以外部化,可以将这些外部状态传入对象中。
- 在使用享元模式时需要维护一个存储享元对象的享元池,而这需要耗费一定的系统资源,因此,应当在需要多次重复使用享元对象时才值得使用享元模式。
十、模式应用
JDK类库中的String类使用了享元模式。
享元模式在编辑器软件中大量使用,如在一个文档中多次出现相同的图片,则只需要创建一个图片对象,通过在应用程序中设置该图片出现的位置,可以实现该图片在不同地方多次重复显示。
https://www.jianshu.com/p/12f025871f17
优质内容筛选与推荐>>
1、BlockingQueue2、字典序的第K小数字3、CentOS7安装Oracle11gR24、Ionic项目打包安卓APK5、推拉模式
长按二维码向我转账
受苹果公司新规定影响,微信 iOS 版的赞赏功能被关闭,可通过二维码转账支持公众号。
阅读
好看
已推荐到看一看
你的朋友可以在“发现”-“看一看”看到你认为好看的文章。
取消
分享想法到看一看
确定
最多200字,当前共字
微信扫一扫
关注该公众号