“享元”指被共享的单元。享元模式就是通过复用对象,以达到节省内存的目的。
尝试复用现有的同类对象,如果未找到匹配的对象,则创建新对象。
意图:运用共享技术有效地支持大量细粒度的对象。
主要解决:在有大量对象时,有可能会造成内存溢出,我们把其中共同的部分抽象出来,如果有相同的业务请求,直接返回在内存中已有的对象,避免重新创建。
享元模式提出了两个要求: 细粒度和共享对象。这里涉及到内部状态和外部状态,即将对象的信息分为两个部分:内部状态和外部状态。
内部状态指对象共享出来的信息,存储在享元对象内部且不会随环境的改变而改变
外部状态指对象得以依赖的一个标记,是随环境改变而改变的、不可共享的状态
以围棋为例,围棋只有黑白二色,其颜色不会随环境改变而改变,所以围棋颜色就是围棋的内部状态,可共享;棋子之间的差别在于位置不同,而落子后,棋子的位置会发生变化,所以棋子的坐标是棋子的外部状态,不可共享。
(1)抽象享元角色(Flyweight):是所有的具体享元类的基类,为具体享元规范需要实现的公共接口,非享元的外部状态以参数的形式通过方法传入。
(2)具体享元角色(Concrete Flyweight):实现抽象享元角色中所规定的接口。
(3)非享元角色(Unsharable Flyweight) :是不可以共享的外部状态,它以参数的形式注入具体享元的相关方法中。
(4)享元工厂(Flyweight Factory)角色:负责创建和管理享元角色。当客户对象请求一个享元对象时,享元工厂检查系统中是否存在符合要求的享元对象,如果存在则提供给客户;如果不存在的话,则创建一个新的享元对象。
以网站项目展示为例,有的要求以新闻形式发布,有的要求以博客形式发布,有的要求以微信公众号形式发布。
整合到一个网站中,共享其相关的代码和数据,对于硬盘、内存、CPU、数据库空间等服务器资源都可以达成共享,减少服务器资源。
//抽象享元角色
public abstract class WebSite {
public abstract void use(User user);
}
//具体享元角色
public class ConcreteWebSite extends WebSite {
private String type = "";//网站发布形式,内部状态,共享部分
public ConcreteWebSite(String type) {
this.type = type;
}
@Override
public void use(User user) {
System.out.println("网站的发布形式为:"+type+","+user.getName()+"在使用");
}
}
//非享元角色
public class User {
private String name;
public User(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
//享元工厂
public class WebSiteFactory {
//集合,充当池的作用
private HashMap pool = new HashMap<>();
//根据网站类型,返回一个网站,如果没有就创建一个并放入池中
public WebSite getWebSiteCategory(String type){
if(!pool.containsKey(type)){
pool.put(type,new ConcreteWebSite(type));
}
return pool.get(type);
}
//获取网站分类数
public int getWebSiteCount(){
return pool.size();
}
}
//客户端
public class Client {
public static void main(String[] args) {
//创建一个工程类
WebSiteFactory webSiteFactory = new WebSiteFactory();
//A以一个新闻形式发布网站
WebSite newsWebsite = webSiteFactory.getWebSiteCategory("新闻");
newsWebsite.use(new User("A"));
//B以一个博客形式发布网站
WebSite blogWebsite1 = webSiteFactory.getWebSiteCategory("博客");
blogWebsite1.use(new User("B"));
//C以一个博客形式发布网站
WebSite blogWebsite2 = webSiteFactory.getWebSiteCategory("博客");
blogWebsite2.use(new User("C"));
//D以一个博客形式发布网站
WebSite blogWebsite3 = webSiteFactory.getWebSiteCategory("博客");
blogWebsite3.use(new User("D"));
//实际网站发布分类实例
System.out.println("实际网站发布分类实例:"+webSiteFactory.getWebSiteCount());
}
}
在Java Integer的实现中,-128到127之间的整型对象会被事先创建好,缓存在IntegerCache类中。当我们使用自动装箱或者valueOf()来创建这个数值区间的整型对象时,会复用IntegerCache类事先创建好的对象。这里的IntegerCache类就是享元工厂类,事先创建好的整型对象就是享元对象。
在Java String类的实现中,JVM开辟一块存储区专门存储字符串常量,这块存储区叫作字符串常量池,类似于Integer中的IntegerCache。不过,跟IntegerCache不同的是,它并非事先创建好需要共享的对象,而是在程序的运行期间,根据需要来创建和缓存字符串常量。
页面更新:2024-02-22
本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828
© CopyRight 2020-2024 All Rights Reserved. Powered By 71396.com 闽ICP备11008920号-4
闽公网安备35020302034903号