一天一个设计模式---享元模式

介绍:这是在这么多种设计模式中极少的以提高程序性能为目的的模式。其主要思想为—如果系统中存在多个相同对象,那么只需要一份对象的拷贝,而不必在每次使用的时候去新建一个对象。

作用:复用对象,节省内存开销和对象创建时间。

优点:
1. 节省重复创建对象的开销
2. 减少内存中的对象数量,进而使得对系统内存的需求也得到减小

一、角色及作用划分

角色作用
享元工厂创建享元类,维护共同的享元对象(核心组件)
抽象享元定义享元所需要实现的业务接口(抽象类或接口)
具体享元类实现抽象享元类,完成具体逻辑
客户端使用享元模式组件,通过享元工厂获取享元对象

二、简单实例

场景:我们设计了一个文本域,如果我们将文本域中的每一个文字都定义为一个对象,那么如果有1万字就需要1万个对象,这会很消耗内存。那么我们就可以考虑使用享元模式来实现。

抽象享元

public interface Font {
    public String createFont();
}

具体享元类

public class BFont implements Font {
    private String tchar;

    public BFont(String tchar) {
        this.tchar = tchar;
    }

    @Override
    public String createFont() {
        return "this is a SizeFont";
    }

    public String getTchar() {
        return tchar;
    }

    public void setTchar(String tchar) {
        this.tchar = tchar;
    }

}

享元工厂

public class FontFactory {
    private static Map<String, Font> fonts = new HashMap<String, Font>();

    public static Font getFont(String tchar) {
        Font font = fonts.get(tchar);
        if (font == null) {
            font = new BFont(tchar);
            fonts.put(tchar, font);
        }
        return font;
    }

}

客户端

public class TestMain {
    public static void main(String[] args) {
        System.out.println(FontFactory.getFont("A"));
        System.out.println(FontFactory.getFont("B"));
        System.out.println(FontFactory.getFont("A"));
    }
}

输出如下:
com.devil.designmodel.flyweight.bfont.BFont@15db9742
com.devil.designmodel.flyweight.bfont.BFont@6d06d69c
com.devil.designmodel.flyweight.bfont.BFont@15db9742

可以看到,同个字母,所使用的对象是相同的

三、扩展实例

场景:在上面场景中,我们只对字母进行判断。如果我们的文字还有颜色和字体大小呢?如果我们的具体实现类分为数字和字母呢?通过对工厂内方法的判断增加逻辑,我们就可以实现这些问题。

抽象享元

public abstract class Font {
    String size;
    String color;

    abstract Font getFont();

    public String getSize() {
        return size;
    }

    public void setSize(String size) {
        this.size = size;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

}

具体享元类

public class CharFont extends Font {
    private String tchar;

    public CharFont(String tchar, String size, String color) {
        this.tchar = tchar;
        this.size = size;
        this.color = color;
    }

    @Override
    String createFont() {
        return "this is CharFont";
    }

    public String getTchar() {
        return tchar;
    }

    public void setTchar(String tchar) {
        this.tchar = tchar;
    }

}
public class NumberFont extends Font {
    private Integer num;

    public NumberFont(Integer num, String size, String color) {
        this.num = num;
        this.size = size;
        this.color = color;
    }

    @Override
    String createFont() {
        return "this is NumberFont";
    }

    public Integer getNum() {
        return num;
    }

    public void setNum(Integer num) {
        this.num = num;
    }

}

享元工厂

public class FontFactory {
    private static Map<Integer, Font> numFont = new HashMap<Integer, Font>();
    private static Map<String, Font> charFont = new HashMap<String, Font>();

    public static NumberFont getNumFont(Integer num, String size, String color) {
        Font f = numFont.get(num);
        if (f == null || !f.getSize().equals(size) || !f.getColor().equals(color)) {
            f = new NumberFont(num, size, color);
            numFont.put(num, f);
        }
        return (NumberFont) f;
    }

    public static CharFont getCharFont(String tchar, String size, String color) {
        Font f = charFont.get(tchar);
        if (f == null || !f.getSize().equals(size) || !f.getColor().equals(color)) {
            f = new CharFont(tchar, size, color);
            charFont.put(tchar, f);
        }
        return (CharFont) f;
    }
}

工厂中将两种类别分开,并对颜色和字体大小也加以验证,保证唯一性和可靠性。


更多模式: 一天一个设计模式—分类与六大原则

更多源码: https://github.com/oDevilo/Java-Base

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值