享元设计模式
兄弟们好,今天我们来聊一下享元设计模式。
相信兄弟们之前一定听过「池化思想」,我们常用的「连接池,线程池,缓冲区和常量池等,这些都是属于池化思想的范畴。」 「而所谓的池化思想就是享元设计模式」
享元设计模式强调的是:「对于重复对象的使用,通过池化思想,控制对象的生成。避免各种小对象不断地产生而造成的内存显露」
享元设计模式的角色:
Flyweight
(抽象享元类):通常是一个接口或者抽象类,声明对外提供的方法ConcreteFlyweight
(具体享元类):实现抽象享元类,可以结合单例设计模式构造一个唯一的享元类UnsharedConcreteFlyweight
(非共享具体享元类):声明一个非共享的享元类,可以直接实例化创建改对象FlyweightFactory
(享元类工厂):用来创建并且管理享元对象,它会将各种类型的具体享元对象存储在一个享元池中,当用户需要一个具体的享元对象时,享元工厂提供一个获取享元对象的方法。
我们来看一下它的类图实现:
- 通过
FlyweightFactory
创建需要的享元对象。- 提供了一个获取
Flyweight
普通的享元对象的方法 - 提供了一个将使用结束的
Flyweight
的对象放回的方法 - 提供了一个创建一个非共享的享元对象的方法
- 提供了一个获取
我们来看一下具体的代码实现
「抽象享元类」
代码语言:javascript复制abstract class Flyweight{
boolean isUsed ;
public Flyweight(boolean isUsed){
this.isUsed = isUsed;
}
abstract void print();
}
「具体享元类」
代码语言:javascript复制class ConcreteFlyweight extends Flyweight{
public ConcreteFlyweight(boolean isUsed){
super(isUsed);
}
public void print(){
System.out.println("这是普通的享元对象");
}
}
「非共享享元类」
代码语言:javascript复制class UnsharedConcreteFlyweight extends Flyweight{
public UnsharedConcreteFlyweight(boolean isUsed){
super(isUsed);
}
public void print(){
System.out.println("这是非共享的享元对象");
}
}
「享元类工厂」
代码语言:javascript复制class FlyweightFactory{
private List<Flyweight> lists = new ArrayList<>();
//创建工厂的时候默认添加5个具体的享元类
{
for(int i = 0 ; i < 5 ; i ){
lists.add(new ConcreteFlyweight(false));
}
}
public Flyweight getFlyweight(){
for (Flyweight flyweight : lists) {
if(!flyweight.isUsed){
//找到未使用的享元类,如果没有则创建一个,并且添加到池中
flyweight.isUsed = true ;
return flyweight ;
}
}
lists.add(new ConcreteFlyweight(true));
return lists.get(lists.size()-1);
}
public boolean setFlyweight(Flyweight flyweight){
//将用完的享元类放回池中
int index = lists.indexOf(flyweight);
if(index == -1){
return false ;
}
lists.get(index).isUsed=false;
return true ;
}
//创建一个非共享的享元类
public Flyweight getShareFlyweight(){
return new UnsharedConcreteFlyweight(true);
}
}
这个就是一个典型的享元设计模式的案例。兄弟们可以看看数据库连接池和线程池怎么设计的,其实思路都类似,都是通过一个集合声明一个池,然后使用的时候直接从里面拿到对象的对象即可。重复利用对象的思想。
还记得昨天的组合设计模式吗?享元设计模式通常会和组合设计模式配合使用,通过组合设计模式将一些叶子节点组合起来,放置到一个池中,然后需要的时候直接获取。