抽丝剥茧——享元设计模式

2021-01-05 22:31:06 浏览数 (1)

享元设计模式

兄弟们好,今天我们来聊一下享元设计模式。

相信兄弟们之前一定听过「池化思想」,我们常用的「连接池,线程池,缓冲区和常量池等,这些都是属于池化思想的范畴。」 「而所谓的池化思想就是享元设计模式」

享元设计模式强调的是:「对于重复对象的使用,通过池化思想,控制对象的生成。避免各种小对象不断地产生而造成的内存显露」

享元设计模式的角色:

  • 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);
    }
}

这个就是一个典型的享元设计模式的案例。兄弟们可以看看数据库连接池和线程池怎么设计的,其实思路都类似,都是通过一个集合声明一个池,然后使用的时候直接从里面拿到对象的对象即可。重复利用对象的思想。

还记得昨天的组合设计模式吗?享元设计模式通常会和组合设计模式配合使用,通过组合设计模式将一些叶子节点组合起来,放置到一个池中,然后需要的时候直接获取。

0 人点赞