享元模式
享元模式,运用共享技术来有效地支持大量细粒度对象的复用。它通过共享已经存在的对象来大幅度减少需要创建的对象数量、避免大量相似类的开销,从而提高系统资源的利用率。
享元模式的优缺点
优点:
-
可以极大减少内存中对象的数量,使得相同或相似对象在内存中只保存一份,从而可以节约系统资源,提高系统性能。
-
享元模式的外部状态相对独立,而且不会影响其内部状态,从而使得享元对象可以在不同的环境中被共享。
缺点:
-
享元模式使得系统变得复杂,需要分离出内部状态和外部状态,这使得程序的逻辑复杂化。
-
为了使对象可以共享,享元模式需要将享元对象的部分状态外部化,而读取外部状态将使得运行时间变长。
享元模式的结构
-
FlyWeight:抽象的享元角色,产品的抽象类,定义了对象的外部状态和内部状态的接口或实现
-
ConcreteFlyWeight:具体的享元角色,产品的实现类,实现了抽象角色定义的相关业务
-
FlyWeightFactory:享元工厂类,内部提供一个池容器,储存ConcreteFlyWeight,同时提供从池中存取数据的操作
实现流程
图书享元类(FlyWeight:抽象的享元角色)
public interface Book {
void read();
}
具体图书(ConcreteFlyWeight:具体的享元角色)
public class FairyBook implements Book {
private String bookName;
public FairyBook(String bookName) {
this.bookName = bookName;
}
public void read() {
System.out.println(bookName + hashCode());//用hashCode区分实例
}
}
图书享元工厂(FlyWeightFactory:享元工厂类)
public class BookFactory {
private Map<String, Book> bookMap = new HashMap<String, Book>();
public FairyBook getFairyBook(String bookName) {
Book book = null;
//根据书名来找书,如果有就直接取,没有就新建
if (bookMap.containsKey(bookName)) {
book = bookMap.get(bookName);
} else {
book = new FairyBook(bookName);
bookMap.put(bookName, book);
}
return (FairyBook) book;
}
}
客户端
BookFactory bookFactory = new BookFactory();
FairyBook fairyBook1 = bookFactory.getFairyBook("格林童话");
fairyBook1.read();
FairyBook fairyBook2 = bookFactory.getFairyBook("小王子");
fairyBook2.read();
FairyBook fairyBook3 = bookFactory.getFairyBook("格林童话");
fairyBook3.read();
输出
格林童话1704856573
小王子705927765
格林童话1704856573//与第一本是同个实例
享元模式与单例模式的区别
单例模式和享元模式都是为了避免重复创建对象,但是其本质是不一样的
- 其实现方式不一样,单例是一个类只有一个唯一的实例,而享元可以有多个实例,只是通过一个共享容器来存储不同的对象。
- 其使用场景不一样,单例是强调减少实例化提升性能,因此一般用于一些需要频繁创建和销毁实例化对象或创建和销毁实例化对象非常消耗资源的类中,如连接池、线程池。而享元则是强调共享相同对象或对象属性,节约内存使用空间。