介绍:这是在这么多种设计模式中极少的以提高程序性能为目的的模式。其主要思想为—如果系统中存在多个相同对象,那么只需要一份对象的拷贝,而不必在每次使用的时候去新建一个对象。
作用:复用对象,节省内存开销和对象创建时间。
优点:
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;
}
}
工厂中将两种类别分开,并对颜色和字体大小也加以验证,保证唯一性和可靠性。
更多模式: 一天一个设计模式—分类与六大原则