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_设计模式之享元模式的更多相关文章

  1. 乐在其中设计模式(C#) - 享元模式(Flyweight Pattern)

    原文:乐在其中设计模式(C#) - 享元模式(Flyweight Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 享元模式(Flyweight Pattern) 作者:weba ...

  2. python设计模式之享元模式

    python设计模式之享元模式 由于对象创建的开销,面向对象的系统可能会面临性能问题.性能问题通常在资源受限的嵌入式系统中出现,比如智能手机和平板电脑.大型复杂系统中也可能会出现同样的问题,因为要在其 ...

  3. 【GOF23设计模式】享元模式

    来源:http://www.bjsxt.com/ 一.[GOF23设计模式]_享元模式.享元池.内部状态.外部状态.线程池.连接池 package com.test.flyweight; /** * ...

  4. 设计模式之享元模式(Flyweight)摘录

    23种GOF设计模式一般分为三大类:创建型模式.结构型模式.行为模式. 创建型模式抽象了实例化过程,它们帮助一个系统独立于怎样创建.组合和表示它的那些对象.一个类创建型模式使用继承改变被实例化的类,而 ...

  5. Head First设计模式之享元模式(蝇量模式)

    一.定义 享元模式(Flyweight Pattern)主要用于减少创建对象的数量,以减少内存占用和提高性能.这种类型的设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结构的方式. ...

  6. 【Unity3D与23种设计模式】享元模式(Flyweight)

    GoF中定义: "使用共享的方式,让一大群小规模对象能更有效地运行" 享元模式一般应用在游戏角色属性设置上 游戏策划需要通过"公式计算"或者"实际测试 ...

  7. Java进阶篇设计模式之七 ----- 享元模式和代理模式

    前言 在上一篇中我们学习了结构型模式的组合模式和过滤器模式.本篇则来学习下结构型模式最后的两个模式, 享元模式和代理模式. 享元模式 简介 享元模式主要用于减少创建对象的数量,以减少内存占用和提高性能 ...

  8. Java设计模式之七 ----- 享元模式和代理模式

    前言 在上一篇中我们学习了结构型模式的组合模式和过滤器模式.本篇则来学习下结构型模式最后的两个模式, 享元模式和代理模式. 享元模式 简介 享元模式主要用于减少创建对象的数量,以减少内存占用和提高性能 ...

  9. 【设计模式】享元模式(Flyweight)

    摘要: 1.本文将详细介绍享元模式的原理和实际代码中特别是Android系统代码中的应用. 纲要: 1. 引入享元模式 2. 享元模式的概念及优缺点介绍 3. 享元模式在Android源码中的应用 1 ...

随机推荐

  1. unittest中忽略某些测试用例的执行

    添加装饰器(@unittest.skip("")) from init import * import unittest class baidu(Info): @unittest. ...

  2. Java 读取excel 文件流

    public static void initType(String path) { try { //1 获取excel文件流 excel xls 文件 暂不支持xlsx if (path.conta ...

  3. XLua----热更新

    一.xLua 环境配置 1).Xlua中  Plugin  Xlua复制到 需要热更新的工程中---->Assets子目录 2).开启宏HOTFIX_ENABLE File---->bui ...

  4. Samba部署共享服务

    在本地PC文件共享 Samba服务程序是一款基于SMB协议并由服务端和客户端组成的开源文件共享资源软件,实现了Windows和Linux系统间的文件共享 1.安装Samba服务程序    yum in ...

  5. 依赖注入[2]: 基于IoC的设计模式

    正如我们在<控制反转>提到过的,很多人将IoC理解为一种"面向对象的设计模式",实际上IoC自身不仅与面向对象没有必然的联系,它也算不上是一种设计模式.一般来讲,设计模 ...

  6. springboot加ES实现全局检索

    ElasticSearch是一个基于Lucene的搜索服务器.它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口.Elasticsearch是用Java开发的,并作为Apach ...

  7. 堆排序应用之topK问题

    题目:求海量数据(正整数)按逆序排列的前k个数(topK),因为数据量太大,不能全部存储在内存中,只能一个一个地从磁盘或者网络上读取数据,请设计一个高效的算法来解决这个问题. 第一行用户输入K,代表要 ...

  8. [Swift]LeetCode89. 格雷编码 | Gray Code

    The gray code is a binary numeral system where two successive values differ in only one bit. Given a ...

  9. [Swift]LeetCode204. 计数质数 | Count Primes

    Count the number of prime numbers less than a non-negative number, n. Example: Input: 10 Output: 4 E ...

  10. [Swift]LeetCode802. 找到最终的安全状态 | Find Eventual Safe States

    In a directed graph, we start at some node and every turn, walk along a directed edge of the graph.  ...