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. Java-JSON 解析

    JSON  JSON(JavaScript Object Notation, JS 对象简谱) 是一种轻量级的数据交换格式.它基于 ECMAScript (欧洲计算机协会制定的js规范)的一个子集,采 ...

  2. TCPDF说明文档

    TCPDF说明文档 一.首先调用TCPDF文件 require_once('tcpdf.php'); 二.实例化TCPDF类 页面方向(P =肖像,L =景观).测量(mm).页面格式 $pdf = ...

  3. 【RL-TCPnet网络教程】第24章 RL-TCPnet之网络控制报文协议ICMP

    第24章     RL-TCPnet之网络控制报文协议ICMP 本章节为大家讲解ICMP(Internet Control Message Protocol,网络控制报文协议),通过前面章节对TCP和 ...

  4. mysql_study_2

    select 代码: CREATE DATABASE mysql_shiyan; use mysql_shiyan; CREATE TABLE department ( dpt_name ) NOT ...

  5. 原有vue项目接入typescript

    原有vue项目接入typescript 为什么要接入typescript javascript由于自身的弱类型,使用起来非常灵活. 这也就为大型项目.多人协作开发埋下了很多隐患.如果是自己的私有业务倒 ...

  6. 动手实现一个 LRU cache

    前言 LRU 是 Least Recently Used 的简写,字面意思则是最近最少使用. 通常用于缓存的淘汰策略实现,由于缓存的内存非常宝贵,所以需要根据某种规则来剔除数据保证内存不被撑满. 如常 ...

  7. 如何实现登录、URL和页面按钮的访问控制?

    用户权限管理一般是对用户页面.按钮的访问权限管理.Shiro框架是一个强大且易用的Java安全框架,执行身份验证.授权.密码和会话管理,对于Shiro的介绍这里就不多说.本篇博客主要是了解Shiro的 ...

  8. JDK1.8源码(三)——java.util.HashMap

      什么是哈希表? 在讨论哈希表之前,我们先大概了解下其他数据结构在新增,查找等基础操作执行性能 数组:采用一段连续的存储单元来存储数据.对于指定下标的查找,时间复杂度为O(1):通过给定值进行查找, ...

  9. C#版[击败100.00%的提交] - Leetcode 6. Z字形变换 - 题解

    版权声明: 本文为博主Bravo Yeung(知乎UserName同名)的原创文章,欲转载请先私信获博主允许,转载时请附上网址 http://blog.csdn.net/lzuacm. C#版 - L ...

  10. 服务测试碰钉子Server GC

    如果发现你的dotnet core服务并发上不去,但cpu资源还比较充足那就要注意了!因为这很有可能是你没有设置一个运行项导致...,下面要提到的就是GC.Server这玩意,实际上项目编译中并没有这 ...