13,享元模式-连连看的图片共享

2024-01-15 08:10

本文主要是介绍13,享元模式-连连看的图片共享,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一,前言

7种结构型设计模式:桥接模式,适配器模式,装饰模式,组合模式,享元模式,外观模式,代理模式上篇我们说了桥接模式:通过将实现和抽象放在两个不同的类层次中而使他们可以独立改变,桥接模式适用于那些多种情况排列组合发生的场景这篇说说享元模式,顾名思义就是共享对象的一种模式
共享对象给我们带来的直接好处就是降低了内存的开销
这个模式并不难,但我们还是要把这个模式涉及到的内容都罗列出来

二,享元模式

1)享元模式的定义:

享元模式:以共享的方式高效的支持大量细粒度对象的重用

2)享元模式的UML图:

享元模式UML

3)享元模式的角色:

FlyWeight抽象享元类:接口或抽象类,声明公共方法,可向外界提供对象的内部状态,设置外部状态。
ConcreteFlyWeight具体享元类:为内部状态提供成员变量进行存储。
UnsharedConcreteFlyWeight非共享享元类:不能被共享的子类可以设计为非共享享元类。
FlyWeightFactory享元工厂类:创建并管理享元对象,享元池一般设计为键值对。

4)内部状态和外部状态

享元对象能做到共享的关键是区分了内部状态和外部状态。 内部状态:可共享,不会随环境改变而改变存储在享元对象内部,构造时通过setter设置
外部状态:不可共享,会随环境改变而改变需要使用时通过客户端传入享元对象且由客户端保存

三,享元模式Demo

1,场景选择和分析

基于享元模式的特点我们选择连连看游戏作为模式场景连连看游戏有以下几适合享元模式的特征:1,内部状态:连连看游戏包含大量重复的图片内容2,外部状态:重复图片中的差异点在于所在位置的不同3,大量重复图片加大了内存的开销,适合使用享元模式

连连看

为了讲解模式我们简化了连连看游戏的场景:1,限制了只有一排图片,单排随机生成10张图片2,客户端保存图片的位置信息(即外部状态)和对象的对应关系3,所有图片对象取自享元工厂4,随机选择两张图片进行比较是否可以消除

2,Demo源码

1)创建一个图片接口,包含获取图片类型(内部状态)和获取图片位置(外部状态)的方法

package com.brave.flyweight;public interface ImageNode {// 获取图片类型-内部状态void getImageType();// 获取图片位置-外部状态void getImageCoordinate(int coordinate);
}

2,实现图片接口创建图片的具体享元类

package com.brave.flyweight;public class CImageNode implements ImageNode {private String imageType;   // 图片类型public CImageNode(String imageType) {this.imageType = imageType;}@Overridepublic void getImageType() {System.out.println("图片类型为 : " + imageType);}@Overridepublic void getImageCoordinate(int coordinate) {System.out.println("图片位置为 : " + coordinate);}}

3,创建享元工厂类,管理享元对象的实例集合

这部分我们就直接将实例初始化到工厂集合中,不再去做懒加载了

package com.brave.flyweight;import java.util.Hashtable;/*** 享元工厂类*  初始化享元工厂,将享元对象装入享元工厂* @author Brave**/
public class ImageNodeFactory {private Hashtable<String, CImageNode> imageNodes = new Hashtable<String, CImageNode>();public ImageNodeFactory(){imageNodes.put("图片1", new CImageNode("图片1"));imageNodes.put("图片2", new CImageNode("图片2"));imageNodes.put("图片3", new CImageNode("图片3"));imageNodes.put("图片4", new CImageNode("图片4"));}// 获取图片对象public ImageNode GetImage(String imageType){return imageNodes.get(imageType);}
}

4)客户端:

package com.brave.flyweight;import java.util.Hashtable;public class Client {public static void main(String[] args) {// 初始化享元工厂ImageNodeFactory imageNodeFactory = new ImageNodeFactory();// Hashtable保存游戏初始化后的图片位置和对象信息Hashtable<Integer, ImageNode> imageList = new Hashtable<Integer,ImageNode>();// 随机初始化游戏数据1-10的随机数int randomNumber = 0;for(int i=0; i<10; i++){randomNumber = (int)(Math.random() * 10);int a = randomNumber/2;//除法switch(a){case 0:imageList.put(i, imageNodeFactory.GetImage("图片1"));break;case 1:imageList.put(i, imageNodeFactory.GetImage("图片2"));break;case 2:imageList.put(i, imageNodeFactory.GetImage("图片3"));break;case 3:imageList.put(i, imageNodeFactory.GetImage("图片4"));break;default:imageList.put(i, imageNodeFactory.GetImage("图片1"));}}System.out.println("随机初始化游戏数据完成,开始打印游戏数据");// 打印游戏数据for(int i=0; i<10; i++){// 外部状态imageList.get(i).getImageCoordinate(i);// 内部状态imageList.get(i).getImageType();}// 随机选取两个不同坐标的图进行比较int A = 0;int B = 0;while(A==B){A = (int)(Math.random() * 10);B = (int)(Math.random() * 10);}// 判断是否是相同对象if(imageList.get(A) == imageList.get(B)){System.out.println("坐标"+A+"和坐标"+B+"的图片相同,可以消除");}else{System.out.println("坐标"+A+"和坐标"+B+"的图片不相同,不可以消除");}}}

5)打印测试日志:

随机初始化游戏数据完成,开始打印游戏数据
图片位置为 : 0
图片类型为 : 图片2
图片位置为 : 1
图片类型为 : 图片1
图片位置为 : 2
图片类型为 : 图片1
图片位置为 : 3
图片类型为 : 图片1
图片位置为 : 4
图片类型为 : 图片3
图片位置为 : 5
图片类型为 : 图片3
图片位置为 : 6
图片类型为 : 图片1
图片位置为 : 7
图片类型为 : 图片1
图片位置为 : 8
图片类型为 : 图片1
图片位置为 : 9
图片类型为 : 图片1
坐标8和坐标9的图片相同,可以消除

四,享元模式的优缺点

优点:由于实现了对象的共享所以极大的减少内存中对象的数量相同或相似的对象内存只保持一份,极大的节约资源,提高系统性能外部状态相对独立,不影响内部变化缺点:共享对象节省内存,共享内部状态,分离了外部状态这使得程序的逻辑复杂化,同时也增加了状态维护成本每次需要对外部的状态进行读取,牺牲了运行时间很显然,这是一种用时间换空间的做法

五,享元模式的应用

JAVA中的String使用了常量池,也就是享元模式,当两个String变量的值都为”abc”时实际使用的是同一个引用

这里我们先标记一下,日后有时间会补充一个了例子

这篇关于13,享元模式-连连看的图片共享的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/608216

相关文章

基于Python实现一个图片拆分工具

《基于Python实现一个图片拆分工具》这篇文章主要为大家详细介绍了如何基于Python实现一个图片拆分工具,可以根据需要的行数和列数进行拆分,感兴趣的小伙伴可以跟随小编一起学习一下... 简单介绍先自己选择输入的图片,默认是输出到项目文件夹中,可以自己选择其他的文件夹,选择需要拆分的行数和列数,可以通过

Java设计模式---迭代器模式(Iterator)解读

《Java设计模式---迭代器模式(Iterator)解读》:本文主要介绍Java设计模式---迭代器模式(Iterator),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,... 目录1、迭代器(Iterator)1.1、结构1.2、常用方法1.3、本质1、解耦集合与遍历逻辑2、统一

Java 线程安全与 volatile与单例模式问题及解决方案

《Java线程安全与volatile与单例模式问题及解决方案》文章主要讲解线程安全问题的五个成因(调度随机、变量修改、非原子操作、内存可见性、指令重排序)及解决方案,强调使用volatile关键字... 目录什么是线程安全线程安全问题的产生与解决方案线程的调度是随机的多个线程对同一个变量进行修改线程的修改操

利用Python脚本实现批量将图片转换为WebP格式

《利用Python脚本实现批量将图片转换为WebP格式》Python语言的简洁语法和库支持使其成为图像处理的理想选择,本文将介绍如何利用Python实现批量将图片转换为WebP格式的脚本,WebP作为... 目录简介1. python在图像处理中的应用2. WebP格式的原理和优势2.1 WebP格式与传统

基于 HTML5 Canvas 实现图片旋转与下载功能(完整代码展示)

《基于HTML5Canvas实现图片旋转与下载功能(完整代码展示)》本文将深入剖析一段基于HTML5Canvas的代码,该代码实现了图片的旋转(90度和180度)以及旋转后图片的下载... 目录一、引言二、html 结构分析三、css 样式分析四、JavaScript 功能实现一、引言在 Web 开发中,

Python如何去除图片干扰代码示例

《Python如何去除图片干扰代码示例》图片降噪是一个广泛应用于图像处理的技术,可以提高图像质量和相关应用的效果,:本文主要介绍Python如何去除图片干扰的相关资料,文中通过代码介绍的非常详细,... 目录一、噪声去除1. 高斯噪声(像素值正态分布扰动)2. 椒盐噪声(随机黑白像素点)3. 复杂噪声(如伪

Python中图片与PDF识别文本(OCR)的全面指南

《Python中图片与PDF识别文本(OCR)的全面指南》在数据爆炸时代,80%的企业数据以非结构化形式存在,其中PDF和图像是最主要的载体,本文将深入探索Python中OCR技术如何将这些数字纸张转... 目录一、OCR技术核心原理二、python图像识别四大工具库1. Pytesseract - 经典O

Redis Cluster模式配置

《RedisCluster模式配置》:本文主要介绍RedisCluster模式配置,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录分片 一、分片的本质与核心价值二、分片实现方案对比 ‌三、分片算法详解1. ‌范围分片(顺序分片)‌2. ‌哈希分片3. ‌虚

Python实现精准提取 PDF中的文本,表格与图片

《Python实现精准提取PDF中的文本,表格与图片》在实际的系统开发中,处理PDF文件不仅限于读取整页文本,还有提取文档中的表格数据,图片或特定区域的内容,下面我们来看看如何使用Python实... 目录安装 python 库提取 PDF 文本内容:获取整页文本与指定区域内容获取页面上的所有文本内容获取

Python基于微信OCR引擎实现高效图片文字识别

《Python基于微信OCR引擎实现高效图片文字识别》这篇文章主要为大家详细介绍了一款基于微信OCR引擎的图片文字识别桌面应用开发全过程,可以实现从图片拖拽识别到文字提取,感兴趣的小伙伴可以跟随小编一... 目录一、项目概述1.1 开发背景1.2 技术选型1.3 核心优势二、功能详解2.1 核心功能模块2.