享元模式 - 结构型模式
模式类型:
Flyweight 享元模式 - 结构型模式
意图:
The intent of this pattern is to use sharing to support a large number of objects that have part of their internal state in common where the other part of state can vary.
运用共享技术有效地支持大量细粒度的对象.
概述:
享元模式的作用在于节省内存开销,对于系统内存在的大量相似的对象,通过享元的设计方式,可以提取出可共享的部分,将其只保留一份进而节省大量的内存开销。
并不是所有的对象都适合进行享元设计,它要求对象具有可共享的特征,这些可共享的特征可以做享元设计,对象的可共享特征比例越大,进行享元设计后节省的内存越多。
注意,对象的不可共享特征不能计入享元设计,所以需要仔细判断区分对象的可共享特征与不可共享特征。
享元模式的本质是:分离和共享。分离的是对象状态中变与不变的部分,共享的是对象中不变的部分。享元模式的关键之处就是在于分离变与不变,把不变的部分作为享元对象的内部状态,把变化的部分作为外部状态,这样享元对象就可以达到共享的目的,从而减少对象数量,节约内存空间。
角色:
1、抽象享元(Flyweight)角色:享元接口,通过这个接口可以接收并作用于外部状态。通过这个接口传入外部的状态,在享元对象的方法处理中可能会使用这些外部状态数据。
2、具体享元(ConcreteFlyweight)角色:具体的享元对象,必须是共享的,需要封装Flyweight的内部状态。
3、非共享的具体享元(UnsharedConcreteFlyweight)角色:非共享的具体享元对象,并不是所有的Flyweight对象都需要共享,非共享的享元对象通常是对共享享元对象的组合对象。
4、享元工厂(FlyweightFactory)角色:享元工厂,主要用来创建并管理共享的享元对象,并对外提供访问共享享元对象的接口。
5、客户端(Client)角色:享元客户端,主要的工作是维持一个对享元对象的引用,计算或存储享元对象的外部状态,也可以访问共享和非共享的享元对象。
模式的应用场景:
1 一个应用程序使用了大量的对象
2 完全由于使用大量的对象,造成很大的存储开销
3 对象的大多数状态都可变为外部状态
4 如果删除对象的外部状态,那么可以用相对较少的共享对象取代很多组对象
5 应用程序不依赖对象标识.由于Flyweight对象可以被共享,对于概念明显有别的想对象,标识测试将返回真值.
结构图:
模式的优缺点:
代码:
网上的实例都差不多,这里还有一个外国网站的(和下面的实例差不多):http://www.tutorialspoint.com/design_pattern/flyweight_pattern.htm
import java.util.HashMap; import java.util.Map; class ServiceContext { private int tableIndex; private String customerName; public ServiceContext(int tableIndex, String customerName) { this.tableIndex = tableIndex; this.customerName = customerName; } public int getTableIndex() { return tableIndex; } public String getCustomerName() { return customerName; } } interface Drink { void provideService(ServiceContext serviceContext); } class Coffee implements Drink { public Coffee() { System.out.println("Coffee is created."); } @Override public void provideService(ServiceContext serviceContext) { System.out.println("Coffee is serving for table " + serviceContext.getTableIndex() + " customer " + serviceContext.getCustomerName()); } } class Tea implements Drink { public Tea() { System.out.println("Drink is created."); } @Override public void provideService(ServiceContext serviceContext) { System.out.println("Drink is serving for table " + serviceContext.getTableIndex() + " customer " + serviceContext.getCustomerName()); } } class Water implements Drink { public Water() { System.out.println("Water is created."); } @Override public void provideService(ServiceContext serviceContext) { System.out.println("Water is serving for table " + serviceContext.getTableIndex() + " customer " + serviceContext.getCustomerName()); } } class DrinkFactory { private Map<String, Drink> drinks = new HashMap<>(); public Drink createDrink(String type) { Drink drink = drinks.get(type); if (drink == null) { // 以下可以考虑抽象工厂模式实现以符合开闭原则,也可以使用反射 if (type.equals("Water")) { drink = new Water(); } else if (type.equals("Tea")) { drink = new Tea(); } else if (type.equals("Coffee")) { drink = new Coffee(); } drinks.put(type, drink); } return drink; } } public class WaiterTest { public static void main(String[] args) { String[] types = {"Water", "Tea", "Coffee"}; DrinkFactory drinkFactory = new DrinkFactory(); for (int i = 1; i <= 9; i++) { Drink drink = drinkFactory.createDrink(types[i % 3]);// Drink 可共享特征 在 DrinkFactory 内部实现享元 ServiceContext serviceContext = new ServiceContext(i, "Sir" + i);// 服务细节为不可共享特征,不能享元 drink.provideService(serviceContext);//外部特征,不可共享特征,保证调用过程不会影响下次调用。 } } }
输出:
Drink is created. Drink is serving for table 1 customer Sir1 Coffee is created. Coffee is serving for table 2 customer Sir2 Water is created. Water is serving for table 3 customer Sir3 Drink is serving for table 4 customer Sir4 Coffee is serving for table 5 customer Sir5 Water is serving for table 6 customer Sir6 Drink is serving for table 7 customer Sir7 Coffee is serving for table 8 customer Sir8 Water is serving for table 9 customer Sir9
可以看出:在9次的服务过程中,饮品只创建了三次,一种饮品都仅仅创建了一次,减小了很多内存开销,服务可以很好的进行。
这就是享元模式的精髓,但务必注意区分出可共享与不可共享部分,保证不可共享部分在使用之后不会影响下次使用,即不会改变可共享部分。
相关模式:
享元模式与单例模式:两者可以组合使用。享元模式中的享元工厂完全可以实现为单例,另外,享元工厂中缓存的享元对象,都是单例实例,可以看成是单例模式的一种变形控制,在享元工厂中来单例享元对象。
享元模式与组合模式:两者可以组合使用。在享元模式中,存在不需要共享软件的享元实现,这些不需要共享的享元通常是对共享的享元对象的组合对象。换句话来说,就是通过将将两种模式组合使用,可以实现更复杂的对象层次结构。
享元模式与状态模式:两者可以组合使用。可以使用享元模式来共享状态模式中的状态对象。通常在状态模式中,会存在数量很大的,细粒度的状态对象,而且它们基本上可以重复使用的,都是用来处理某一个固定的状态的,它们需要的数据通常都是由上下文传入,也就是变化部分都被分离出去呢,所以可以用享元模式来实现这些状态对象呢。
享元模式与策略模式:两者可以组合使用。也可以使用享元来实现策略模式中的策略对象。和状态模式一样,策略模式中也存在大量细粒度的策略对象,它们需要的数据同样也是从上下文传入的,因而可以通过享元模式来实现这些策略对象。
所有模式:
创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
补充模式:空对象模式
原文地址:https://blog.csdn.net/paincupid/article/details/46896653
转载于:https://www.cnblogs.com/tartis/p/9288750.html
享元模式 - 结构型模式相关推荐
- 代理模式——结构型模式(7)
前言 今天我们将介绍的最后一种结构型模式--代理模式,在介绍它之前,让我们先回顾下上一篇博文对享元模式的学习.享元模式主要是通过运用共享技术有效支持大量细粒度的对象,其本质在于两方面:分离和共享.简单 ...
- 【设计模式】设计模式总结 ( 七大设计原则 | 创建型模式 | 结构型模式 | 行为型模式 ) ★★★
文章目录 一.七大设计原则 1.开闭原则 2.依赖倒置原则 3.单一职责原则 4.接口隔离原则 5.迪米特原则 6.里氏替换原则 7.合成复用原则 二.创建型模式 0.简单工厂模式 ( 不属于 GOF ...
- 设计模式笔记 10.Facade 外观模式(结构型模式)
10. Facade 外观模式 2008-8-18 动机(Motivation) 上述A方案的问题在于组件的客户和组件中各种复杂的子系统有了过多的耦合,随着外部客户程序和各子系统的演化,这种 ...
- 设计模式(八):Bridge桥接模式 -- 结构型模式
1. 概述 在软件系统中,某些类型由于自身的逻辑,它具有两个或多个维度的变化,那么如何应对这种"多维度的变化"?如何利用面向对象的技术来使得该类型能够轻松的沿着多个方向进行变化,而 ...
- 设计模式深入学习---Component组合模式(结构型模式)
Component组合模式是一个非常好用而且经常可以在大型项目中看到的设计模式. 首先我们来简单过一下什么是Component组合模式以及用该模式的情况和好处.Component组合模式就是将对 ...
- 备战面试日记(3.3) - (设计模式.23种设计模式之结构型模式)
本人本科毕业,21届毕业生,一年工作经验,简历专业技能如下,现根据简历,并根据所学知识复习准备面试. 记录日期:2022.1.9 大部分知识点只做大致介绍,具体内容根据推荐博文链接进行详细复习. 文章 ...
- 设计模式(2)结构型模式
结构型模式 结构型模式介绍如何将对象和类组装成较大的结构, 并同时保持结构的灵活和高效. 结构型模式: 适配器模式:用来把一个接口转化成另一个接口.使得原本由于接口不兼容而不能一起工作的那些类可以在一 ...
- 23种设计模式:(二)结构型模式
根据北京尚学堂的视频所学习 结构型模式: 核心作用:是从程序的结构上实现松耦合,从而可以扩大整体的类结构,用来解决更大的问题. 分类: 适配器模式.代理模式.桥接模式. 装饰模式.组合模式.外观模式. ...
- 设计模式 - 结构型模式_外观模式
文章目录 结构型模式 概述 Case Bad Impl Better Impl 小结 结构型模式 结构型模式主要是解决如何将对象和类组装成较大的结构, 并同时保持结构的灵活和⾼效. 结构型模式包括:适 ...
最新文章
- 使用osql.exe, 将Select的内容保存为文件
- RESTful API 中的 Status code 是否要遵守规范
- 关于win7禁止标准用户安装软件 AppLocker使用
- 【开源项目】基于FFmpeg的PCM数据编码为AAC
- [GCJ] Qualification Round 2017
- oracle数据设置为ull,Oracle _11g_使用手册_自备
- python2和python3共存时,设置默认python为python3
- 混合选择集的坐标提起lisp_晓东CAD家园-论坛-A/VLISP-[LISP程序]:请教如何对选择集进行排序-我有(setq ss(ssget _w p0 p1 (list (0 . CIRC...
- useragent 全集 firefox插件 useragetn switch 使用
- dematel matlab,决策与实验室方法,DEMATEL分析方法介绍
- 几步操作即可实现WhatsApp群发
- Android触摸事件进行画图简单实现
- 2021年中国电力行业境外电力项目签约额分析:实现签约项目536个 签约合同总金额440.6亿美元[图]
- 马悦凌:从初级护士到“民间奇医”[6]
- Linux启用显卡opengl,如何使你的Nvidia显卡支持OpenGL?
- CCF系列题解--2016年9月第二题 火车购票
- OLED滑动显示长字符
- 银川水利学校计算机专业怎么样,黄河水利职业技术学院的计算机专业怎么样
- 京东商城的融资诱惑与亏损陷阱
- 机器人softmove_ABB机器人机床上下料工作站——ABB机器人
热门文章
- 【Ubuntu-caffe-anaconda3】安装错误总结
- 936焊台(恒温电烙铁)温度不可调的维修 (Z)
- MySQL Fabric 实践
- 迁移学习 迁移参数_迁移学习简介
- 一种数据结构 跳表skiplist
- 一个有意思的CStatic和combobox以及Cedit控件结合使用
- 了解OPhone平台---OPhone平台架构和主要开发组件
- weblogic jms消息 删除_消息队列与消息中间件概述:消息中间件核心概念与技术选型...
- python类有什么用_python 定制类 有什么用
- python 可视化_python可视化基础