享元模式详解(4大角色及应用场景实例)

享元模式详解(4大角色及应用场景实例)-mikechen

享元模式定义

享元模式:“享”就是分享之意,指一物被众人共享,而这也正是该模式的宗旨所在。

享元模式有点类似于单例模式,都是只生成一个对象来被共享使用。

 

享元模式作用

享元模式的作用:主要用于减少创建对象的数量,以减少内存占用和提高性能。

比如:当一个系统中存在大量重复对象的时候,如果这些重复的对象是「不可变对象」,我们就可以利用享元模式将对象设计成享元,在内存中只保留一份实例,供多处代码引用,这样可以减少内存中对象的数量,起到节省内存的目的。

 

享元模式应用场景

享元模式经典的应用场景,典型的有两类:

  • 一类就是:系统中存在大量的相似对象;
  • 另外一类就是:就是池技术;

比如:String常量池、数据库连接池、缓冲池等等,都是享元模式的应用,享元模式是池技术的重要实现方式。

 

享元模式角色

享元模式主要包含4大角色,如下图所示:

享元模式详解(4大角色及应用场景实例)-mikechen

1.抽象享元角色(Flyweight)角色

是所有的具体享元类的基类,为具体享元规范需要实现的公共接口,非享元的外部状态以参数的形式通过方法传入。

2.具体享元(Concrete Flyweight)角色

实现抽象享元角色中所规定的接口。

3.非享元(Unsharable Flyweight)角色

是不可以共享的外部状态,它以参数的形式注入具体享元的相关方法中。

4.享元工厂(Flyweight Factory)角色

负责创建和管理享元角色。当客户对象请求一个享元对象时,享元工厂检査系统中是否存在符合要求的享元对象,如果存在则提供给客户;如果不存在的话,则创建一个新的享元对象。

 

享元模式示例

下面我们来看一个享元模式的例子,源码如下:

package Flyweight;
 
import java.util.ArrayList;
import java.util.HashMap;
 
public class Sportgame {
 
    private static final ArrayList<String> Consumption_msg = new ArrayList<String>();
 
    private static void addmsg(String msg) {
        Consumption_msg.add(msg);
    }
 
    public static void main(String[] args) {
        addmsg("重庆体育馆");
        addmsg("上海体育馆");
        addmsg("北京体育馆");
        addmsg("重庆体育馆");
        addmsg("重庆体育馆");
        addmsg("北京体育馆");
        addmsg("上海体育馆");
        addmsg("重庆体育馆");
        addmsg("北京体育馆");
 
        for (String e : Consumption_msg) {
            SoccerFactory.getSoccer(e).display();
        }
    }
 
}
 
 
//享元工厂
class SoccerFactory{
    private static HashMap<String,Gym> e = new HashMap<String,Gym>();
    
    public static Gym getSoccer(String gymName) {
        Gym gym = e.get(gymName);
        
        if(gym == null) {
            gym = new Gym(gymName);
            e.put(gymName, gym);
        }
 
        return gym;
        
    }
    
}
 
//具体享元
class Gym implements Soccer{
    String gymName;
    String sport = "足球";
    double price = 500;
    
    public Gym(String gymName) {
        this.gymName = gymName;
    }
 
    public void setSport(String sport) {
        this.sport = sport;
    }
 
    public void setPrice(double price) {
        this.price = price;
    }
 
    @Override
    public void display() {
        // TODO Auto-generated method stub
        System.out.println("{In[" + gymName + "],[Progect:" + sport + "],[Price:" + price
                + "]["+this+"]}");
    }
    
    
}
//抽象享元
interface Soccer{
    public void display();
}

以上享元模式的4大角色分别对应:

  • 抽象享元角色:Soccer类(足球);
  • 具体享元角色:Gym类(体育馆);
  • 非享元角色:本文将非享元角色类合并在具体享元角色中,例如:变量sport,price;
  • 享元工厂角色:SoccerFactory类,负责创建和管理享元角色。

 

 

作者简介

陈睿|mikechen,10年+大厂架构经验,BAT资深面试官,就职于阿里巴巴、淘宝、百度等一线互联网大厂。

👇阅读更多mikechen架构文章👇

阿里架构 |双11秒杀 |分布式架构 |负载均衡 |单点登录 |微服务 |云原生 |高并发 |架构师

以上

关注作者「mikechen」公众号,获取更多技术干货!

后台回复架构,即可获取《阿里架构师进阶专题全部合集》,后台回复面试即可获取《史上最全阿里Java面试题总结

评论交流
    说说你的看法