动机
- 在软件系统采用纯粹对象方案的问题在于大量细粒度的对象会很快充斥在系统中,从而带来很高的运行时代价—主要指内存需求方面的代价。
- 如何在避免大量细粒度对象问题的同时,让外部客户程序仍然能够透明地使用面向对象的方式来进行操作?
模式定义
运用共享技术有效地支持大量细粒度的对象。
享元:共享元对象,使用了对象池的概念,把一系列对象放入对象容器中。
类图
总结
- 面向对象很好的解决了抽象性的问题,但是作为一个运行在机器中的程序实体,我们需要考虑对象的代价问题。Flyweight主要解决面向对象的代价问题,一般不触及面向对象的抽象性问题。
- Flyweight采用对象共享的做法来降低系统中对象的个数,从而降低细粒度对象给系统带来的内存压力。在具体实现方面,要注意对象状态的处理。
- 对象的数量太大从而导致对象内存开销加大—什么样的数量才算大?这需要我们仔细的根据具体应用情况进行评估,而不能凭空臆断。
实例
场景:
通过字体的显示问题,来描述享元模式的问题,考虑的字体是非常细粒度的对象,同时也是大量存在的,使用享元模式可以提高程序的性能。
注意享元模式和单例模式强调的是性能,不强调抽象,因此我们会看到类中会有具体的类,没有依赖抽象,通常比较紧耦合。
- 定义字体接口和具体的字体类
public interface IFont {
void display();
}
public class SongFont implements IFont{
private int size;
@Override
public void display() {
System.out.println("Song ti display");
}
}
- 定义字体工厂,核心是类中的对象池技术,对象池是实现共享的保证。
/**
* 不考虑多线程问题
*/
public class FontFactory {
// 享元模式的核心就是对象池
private volatile Map<String, IFont> fontMap = new HashMap<>();
public IFont getFont(final String key) {
if (fontMap.get(key) == null) {
fontMap.put(key, new SongFont());
}
return fontMap.get(key);
}
}
- 客户端调用类,分别获取同一种字体,查看hashcode是相同的,证明使用的是同一个对象。
public class Client {
public static void main(String[] args) {
FontFactory fontFactory = new FontFactory();
IFont font = fontFactory.getFont("song");
System.out.println(font.hashCode());
font.display();
IFont font1 = fontFactory.getFont("song");
System.out.println(font.hashCode());
}
}
// 打印信息
1872034366
Song ti display
1872034366
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/100408.html