Java_设计模式之享元模式
1、关于享元模式
享元模式有点类似于单例模式,都是只生成一个对象被共享使用。享元模式主要目的就是让多个对象实现共享,减少不会要额内存消耗,将多个对同一对象的访问集中起来,不必为每个访问者创建一个单独的对象,以此来降低内存的消耗。
2、享元模式结构图
因为享元模式结构比较复杂,一般结合工厂模式一起使用,在它的结构图中包含了一个享元工厂类。
在享元模式结构图中包含如下几个角色:
Flyweight(抽象享元类):通常是一个接口或抽象类,在抽象享元类中声明了具体享元类公共的方法,这些方法可以向外界提供享元对象的内部数据(内部状态),同时也可以通过这些方法来设置外部数据(外部状态)。
ConcreteFlyweight(具体享元类):它实现了抽象享元类,其实例称为享元对象;在具体享元类中为内部状态提供了存储空间。通常我们可以结合单例模式来设计具体享元类,为每一个具体享元类提供唯一的享元对象。
UnsharedConcreteFlyweight(非共享具体享元类):并不是所有的抽象享元类的子类都需要被共享,不能被共享的子类可设计为非共享具体享元类;当需要一个非共享具体享元类的对象时可以直接通过实例化创建。
FlyweightFactory(享元工厂类):享元工厂类用于创建并管理享元对象,它针对抽象享元类编程,将各种类型的具体享元对象存储在一个享元池中,享元池一般设计为一个存储“键值对”的集合(也可以是其他类型的集合),可以结合工厂模式进行设计;当用户请求一个具体享元对象时,享元工厂提供一个存储在享元池中已创建的实例或者创建一个新的实例(如果不存在的话),返回新创建的实例并将其存储在享元池中。
3、享元模式的实现
在享元模式中引入了享元工厂类,享元工厂类的作用在于提供一个用于存储享元对象的享元池,当用户需要对象时,首先从享元池中获取,如果享元池中不存在,则创建一个新的享元对象返回给用户,并在享元池中保存该新增对象。
接下来,实现一个登陆的享元模式。
1、用户类
/**
* 用户类
* @author 董秀才
*
*/
public class User {
private String username; // 用户名
private String password; // 密码 public User(String username,String password) {
this.username = username;
this.password = password;
} public String getUsername() {
return username;
} public void setUsername(String username) {
this.username = username;
} public String getPassword() {
return password;
} public void setPassword(String password) {
this.password = password;
}
}
2、抽象的登陆者(抽象享元类)
/**
* 登陆者--抽象享元类
* @author 董秀才
*
*/
public abstract class Loginer { //登陆--享元类公共方法
public abstract void login(User user); }
3、具体的登陆者(具体享元类)
/**
* 具体享元类
* @author 董秀才
*
*/
public class ConcreteLoginer extends Loginer{ // 登陆者凭证
private String loginerKey = "";
public ConcreteLoginer(String loginerKey) {
this.loginerKey = loginerKey;
} @Override
public void login(User user) {
System.out.println("登陆者凭证:" + this.loginerKey+",用户名:" + user.getUsername() + ",密码:" + user.getPassword());
} }
4、具体登陆者的工厂类(享元工厂类)
/**
* 享元工厂类
* @author 董秀才
*
*/
public class ConcreteLoginerFactory { // map充当对象享元池
private static Map<String,ConcreteLoginer> loginerMap = new HashMap<String, ConcreteLoginer>(); public static ConcreteLoginer getConcreteLoginer(String key) {
// 从享元池中拿 登陆者对象
ConcreteLoginer concreteLoginer = loginerMap.get(key);
// 如果享元池中没有此对象
if(concreteLoginer == null) {
// 创建对象
concreteLoginer = new ConcreteLoginer(key);
// 存到享元池中
loginerMap.put(key, concreteLoginer);
}
// 返回对象
return concreteLoginer;
} // 返回享元池对象数量
public static int getSize() {
return loginerMap.size();
}
}
5、测试类
/**
* 博客测试类
* @author 董秀才
*
*/
public class MainTest { public static void main(String[] args) {
// 去工厂拿对象
ConcreteLoginer concreteLoginer_1 = ConcreteLoginerFactory.getConcreteLoginer("csdn");
concreteLoginer_1.login(new User("董秀才","123456")); ConcreteLoginer concreteLoginer_2 = ConcreteLoginerFactory.getConcreteLoginer("csdn");
concreteLoginer_2.login(new User("董秀才","123456")); ConcreteLoginer concreteLoginer_3 = ConcreteLoginerFactory.getConcreteLoginer("csdn");
concreteLoginer_3.login(new User("董秀才","123456")); // 测试是否是同一个对象
System.out.println("是否是同一个对象:" + ((concreteLoginer_1==concreteLoginer_2)&&(concreteLoginer_2 == concreteLoginer_3))); // 第二登陆者
ConcreteLoginer concreteLoginer_4 = ConcreteLoginerFactory.getConcreteLoginer("博客园");
concreteLoginer_4.login(new User("董才才","654321")); ConcreteLoginer concreteLoginer_5 = ConcreteLoginerFactory.getConcreteLoginer("博客园");
concreteLoginer_5.login(new User("董才才","654321")); ConcreteLoginer concreteLoginer_6 = ConcreteLoginerFactory.getConcreteLoginer("博客园");
concreteLoginer_6.login(new User("董才才","654321")); System.out.println("是否是同一个对象:" + ((concreteLoginer_4==concreteLoginer_5)&&(concreteLoginer_5 == concreteLoginer_6)));
// 工厂类中享元池中对象数量
System.out.println("享元池size:" + ConcreteLoginerFactory.getSize());
} }
6、运行结果
4、总结
从上面代码和运行结果这可以看到,同一个登陆者登陆时是 "享" 用同一个登陆者对象。在享元对象池中只有两个对象。
享元模式优点
享元模式的外部状态相对独立,使得对象可以在不同的环境中被复用(共享对象可以适应不同的外部环境)
享元模式可共享相同或相似的细粒度对象,从而减少了内存消耗,同时降低了对象创建与垃圾回收的开销
享元模式缺点
外部状态由客户端保存,共享对象读取外部状态的开销可能比较大
享元模式要求将内部状态与外部状态分离,这使得程序的逻辑复杂化,同时也增加了状态维护成本
Java_设计模式之享元模式的更多相关文章
- 乐在其中设计模式(C#) - 享元模式(Flyweight Pattern)
原文:乐在其中设计模式(C#) - 享元模式(Flyweight Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 享元模式(Flyweight Pattern) 作者:weba ...
- python设计模式之享元模式
python设计模式之享元模式 由于对象创建的开销,面向对象的系统可能会面临性能问题.性能问题通常在资源受限的嵌入式系统中出现,比如智能手机和平板电脑.大型复杂系统中也可能会出现同样的问题,因为要在其 ...
- 【GOF23设计模式】享元模式
来源:http://www.bjsxt.com/ 一.[GOF23设计模式]_享元模式.享元池.内部状态.外部状态.线程池.连接池 package com.test.flyweight; /** * ...
- 设计模式之享元模式(Flyweight)摘录
23种GOF设计模式一般分为三大类:创建型模式.结构型模式.行为模式. 创建型模式抽象了实例化过程,它们帮助一个系统独立于怎样创建.组合和表示它的那些对象.一个类创建型模式使用继承改变被实例化的类,而 ...
- Head First设计模式之享元模式(蝇量模式)
一.定义 享元模式(Flyweight Pattern)主要用于减少创建对象的数量,以减少内存占用和提高性能.这种类型的设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结构的方式. ...
- 【Unity3D与23种设计模式】享元模式(Flyweight)
GoF中定义: "使用共享的方式,让一大群小规模对象能更有效地运行" 享元模式一般应用在游戏角色属性设置上 游戏策划需要通过"公式计算"或者"实际测试 ...
- Java进阶篇设计模式之七 ----- 享元模式和代理模式
前言 在上一篇中我们学习了结构型模式的组合模式和过滤器模式.本篇则来学习下结构型模式最后的两个模式, 享元模式和代理模式. 享元模式 简介 享元模式主要用于减少创建对象的数量,以减少内存占用和提高性能 ...
- Java设计模式之七 ----- 享元模式和代理模式
前言 在上一篇中我们学习了结构型模式的组合模式和过滤器模式.本篇则来学习下结构型模式最后的两个模式, 享元模式和代理模式. 享元模式 简介 享元模式主要用于减少创建对象的数量,以减少内存占用和提高性能 ...
- 【设计模式】享元模式(Flyweight)
摘要: 1.本文将详细介绍享元模式的原理和实际代码中特别是Android系统代码中的应用. 纲要: 1. 引入享元模式 2. 享元模式的概念及优缺点介绍 3. 享元模式在Android源码中的应用 1 ...
随机推荐
- Golang Go Go Go part3:数据类型及操作
五.Go 基本类型 1.基本类型种类 布尔值: bool 长度 1字节 取值范围 true, false注意事项:不可用数字代表 true 或 false 整型: int/uint 根据运行平台可能为 ...
- MP3、MP4的文件选择及播放
项目主页网址如下: https://github.com/Judylalala/en ####技术问题1:如何播放音频(MP3).视频(MP4)? ####解决过程1:我首先想到了XMAL插件中的Me ...
- WPF:How to display a Bitmap on Image control
一个Bitmap文件,叫做screenShotFile, 你可以这样显示到Image控件上. BitmapImage bi = new BitmapImage(); bi.Beg ...
- SQL Server 2017 新功能分享
本篇文章是我在MVP直通车分享的关于SQL Server 2017的新功能,现在ppt分享如下,可以点击这里下载.
- Kali学习笔记42:SQL手工注入(4)
前三篇文章都是在讲发现SQL注入漏洞 如何查询得到所有的信息 那么另一条思路还未尝试过:能否修改数据? 例如这样: '; update users set user='yiqing' where us ...
- [Swift]LeetCode684. 冗余连接 | Redundant Connection
In this problem, a tree is an undirected graph that is connected and has no cycles. The given input ...
- Java操作符真的简单到易如反掌?
之前我写了一篇<吃人的那些Java名词:对象.引用.堆.栈和堆栈>,本以为凭借自己8年的Java编程经验足够把这些“吃人”的Java名词解释清楚了,但有网友不以为然,在文章底部评论说:“老 ...
- 程序员如何面试才能拿到offer
一.概述 面试,难还是不难?取决于面试者的底蕴(气场+技能).心态和认知及沟通技巧.面试其实可以理解为一场聊天和谈判,在这过程中有心理.思想上的碰撞和博弈.其实你只需要搞清楚一个逻辑:“面试官为什么会 ...
- .Net Core中的Api版本控制
原文链接:API Versioning in .Net Core 作者:Neel Bhatt 简介 Api的版本控制是Api开发中经常遇到的问题, 在大部分中大型项目都需要使用到Api的版本控制 在本 ...
- redis 系列25 哨兵Sentinel (高可用演示 下)
一. Sentinel 高可用环境准备 1.1 Sentinel 集群环境 环境 说明 操作系统版本 CentOS 7.4.1708 IP地址 172.168.18.200 网关Gateway 1 ...