草庐IT

享元模式

runoob 2023-04-06 原文

享元模式

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

享元模式尝试重用现有的同类对象,如果未找到匹配的对象,则创建新对象。我们将通过创建 5 个对象来画出 20 个分布于不同位置的圆来演示这种模式。由于只有 5 种可用的颜色,所以 color 属性被用来检查现有的 Circle 对象。

介绍

意图:运用共享技术有效地支持大量细粒度的对象。

主要解决:在有大量对象时,有可能会造成内存溢出,我们把其中共同的部分抽象出来,如果有相同的业务请求,直接返回在内存中已有的对象,避免重新创建。

何时使用: 1、系统中有大量对象。 2、这些对象消耗大量内存。 3、这些对象的状态大部分可以外部化。 4、这些对象可以按照内蕴状态分为很多组,当把外蕴对象从对象中剔除出来时,每一组对象都可以用一个对象来代替。 5、系统不依赖于这些对象身份,这些对象是不可分辨的。

如何解决:用唯一标识码判断,如果在内存中有,则返回这个唯一标识码所标识的对象。

关键代码:用 HashMap 存储这些对象。

应用实例: 1、JAVA 中的 String,如果有则返回,如果没有则创建一个字符串保存在字符串缓存池里面。 2、数据库的连接池。

优点:大大减少对象的创建,降低系统的内存,使效率提高。

缺点:提高了系统的复杂度,需要分离出外部状态和内部状态,而且外部状态具有固有化的性质,不应该随着内部状态的变化而变化,否则会造成系统的混乱。

使用场景: 1、系统有大量相似对象。 2、需要缓冲池的场景。

注意事项: 1、注意划分外部状态和内部状态,否则可能会引起线程安全问题。 2、这些类必须有一个工厂对象加以控制。

实现

我们将创建一个 Shape 接口和实现了 Shape 接口的实体类 Circle。下一步是定义工厂类 ShapeFactory

ShapeFactory 有一个 CircleHashMap,其中键名为 Circle 对象的颜色。无论何时接收到请求,都会创建一个特定颜色的圆。ShapeFactory 检查它的 HashMap 中的 circle 对象,如果找到 Circle 对象,则返回该对象,否则将创建一个存储在 hashmap 中以备后续使用的新对象,并把该对象返回到客户端。

FlyWeightPatternDemo 类使用 ShapeFactory 来获取 Shape 对象。它将向 ShapeFactory 传递信息(red / green / blue/ black / white),以便获取它所需对象的颜色。

步骤 1

创建一个接口。

Shape.java

public interface Shape { void draw(); }

步骤 2

创建实现接口的实体类。

Circle.java

public class Circle implements Shape { private String color; private int x; private int y; private int radius; public Circle(String color){ this.color = color; } public void setX(int x) { this.x = x; } public void setY(int y) { this.y = y; } public void setRadius(int radius) { this.radius = radius; } @Override public void draw() { System.out.println("Circle: Draw() [Color : " + color +", x : " + x +", y :" + y +", radius :" + radius); } }

步骤 3

创建一个工厂,生成基于给定信息的实体类的对象。

ShapeFactory.java

import java.util.HashMap; public class ShapeFactory { private static final HashMap<String, Shape> circleMap = new HashMap<>(); public static Shape getCircle(String color) { Circle circle = (Circle)circleMap.get(color); if(circle == null) { circle = new Circle(color); circleMap.put(color, circle); System.out.println("Creating circle of color : " + color); } return circle; } }

步骤 4

使用该工厂,通过传递颜色信息来获取实体类的对象。

FlyweightPatternDemo.java

public class FlyweightPatternDemo { private static final String colors[] = { "Red", "Green", "Blue", "White", "Black" }; public static void main(String[] args) { for(int i=0; i < 20; ++i) { Circle circle = (Circle)ShapeFactory.getCircle(getRandomColor()); circle.setX(getRandomX()); circle.setY(getRandomY()); circle.setRadius(100); circle.draw(); } } private static String getRandomColor() { return colors[(int)(Math.random()*colors.length)]; } private static int getRandomX() { return (int)(Math.random()*100 ); } private static int getRandomY() { return (int)(Math.random()*100); } }

步骤 5

执行程序,输出结果:

Creating circle of color : Black
Circle: Draw() [Color : Black, x : 36, y :71, radius :100
Creating circle of color : Green
Circle: Draw() [Color : Green, x : 27, y :27, radius :100
Creating circle of color : White
Circle: Draw() [Color : White, x : 64, y :10, radius :100
Creating circle of color : Red
Circle: Draw() [Color : Red, x : 15, y :44, radius :100
Circle: Draw() [Color : Green, x : 19, y :10, radius :100
Circle: Draw() [Color : Green, x : 94, y :32, radius :100
Circle: Draw() [Color : White, x : 69, y :98, radius :100
Creating circle of color : Blue
Circle: Draw() [Color : Blue, x : 13, y :4, radius :100
Circle: Draw() [Color : Green, x : 21, y :21, radius :100
Circle: Draw() [Color : Blue, x : 55, y :86, radius :100
Circle: Draw() [Color : White, x : 90, y :70, radius :100
Circle: Draw() [Color : Green, x : 78, y :3, radius :100
Circle: Draw() [Color : Green, x : 64, y :89, radius :100
Circle: Draw() [Color : Blue, x : 3, y :91, radius :100
Circle: Draw() [Color : Blue, x : 62, y :82, radius :100
Circle: Draw() [Color : Green, x : 97, y :61, radius :100
Circle: Draw() [Color : Green, x : 86, y :12, radius :100
Circle: Draw() [Color : Green, x : 38, y :93, radius :100
Circle: Draw() [Color : Red, x : 76, y :82, radius :100
Circle: Draw() [Color : Blue, x : 95, y :82, radius :100

有关享元模式的更多相关文章

  1. java - dom4j库是如何实现享元模式的? - 2

    我可以在dom4j库中看到许多带有Flyweight前缀的类:FlyweightAttribute、FlyweightComment、FlyweightText等。这是java文档在FlyweightText的情况下所说的:享元文本是单链接、只读XML文本的享元模式实现。该节点可以跨文档和元素共享,但它不支持父关系。但是,我似乎无法在代码实例池中找到这些实例在文档之间共享的位置。库中是否完全实现了此功能?如果是,实现它的代码在哪里? 最佳答案 我刚刚查看了1.6.1的源代码。看起来这些Flyweight类只是原始想法的和平。至少它们

  2. c# - 了解享元模式 - 2

    Intent:Theintentofthispatternistousesharingtosupportalargenumberofobjectsthathavepartoftheirinternalstateincommonwheretheotherpartofstatecanvary.对象可以通过静态字段共享状态。使用享元模式和使用静态字段共享大量对象的内部状态有什么区别?享元通过其工厂提供的对象池是享元的真正含义吗? 最佳答案 使用静态字段,在任何一个时间点只能有一个对象实例在使用中。使用享元模式,您可以同时使用任意数量的不同

  3. php - 依赖注入(inject)和工作单元模式 - 2

    我有一个难题。我使用DI(阅读:工厂)为自制ORM提供核心组件。容器根据请求提供数据库连接、DAO、映射器及其生成的域对象。这是映射器和域对象类的基本概述classMapper{publicfunction__constructor($DAO){$this->DAO=$DAO;}publicfunctionload($id){if(isset(Monitor::members[$id]){returnMonitor::members[$id];$values=$this->DAO->selectStmt($id);//fieldmappingprocessomittedforbrevi

  4. java - 如何在 JPA 2.0 元模型中自动生成列名作为静态最终字符串? - 2

    在一些JPA注释中,我想在代码中直接使用字段名称来代替容易出错的字符串:@javax.persistence.OrderBy(value=User_.registrationDate.getName())publicListgetPlugConfigs(){...}但上面的代码不会编译,因为要获取名称,我必须使用不是常量表达式的函数(User_是JPA@StaticMetamodel生成的)。是否可以以任何方式为此使用元模型,或者我是否坚持使用直接字符串常量?有没有办法为元模型自动生成这样的字符串常量?(我正在使用maven-processor-plugin生成)

  5. java - 为什么编译器不识别元模型属性? - 2

    javase6项目是否支持eclipselinkjpa2的criteriaapi?如果没有,那是我的问题。我是否需要在persistence.xml中为条件api指定任何特殊内容?这是我的条件查询:finalEntityTypeMeaning_=em.getMetamodel().entity(Meaning.class);finalCriteriaBuildercb=em.getCriteriaBuilder();CriteriaQuerycq=cb.createQuery(Integer.class);finalRootmeng=cq.from(Meaning.class);cq.

  6. java - 那里有任何 Java 享元模式实现吗? - 2

    很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visitthehelpcenter.关闭11年前。我一直在寻找享元模式的实现,并在到达Google搜索的第20页后放弃了。虽然那里有无数愚蠢的例子,但似乎没有人发布过Java中的可重用实现。对我来说,flyweight只有在您必须保留许多这样的实例时才真正有意义,因此它必须作为一个集合来实现。我想要的是一个采用byte/short/int/longmapper实现并返回List、Set或Map的工厂,它看起来像一个普通的对象集合,但在内部存储它

  7. java - 嵌入式的 JPA 2 XML 映射,以便它与 Hibernate 元模型生成器一起工作 - 2

    我想为Hibernate(版本1.1.1-Final)(在Spring应用程序中)使用JPA2元模型生成器。因为我使用一个映射父类(superclass),它是所有实体的基础,并且这个类位于不同的jar中(为了重用)我需要在XML中显式映射这个类(仅用于元模型生成,因为它有效没有任何额外的时间)---可能有人会提示如何解决这个问题,但这不是问题。此映射的父类(superclass)(BusinessEntity)使用嵌入式类(BusinessId)。@SuppressWarnings("serial")@MappedSuperclasspublicabstractclassBusine

  8. java - 使用 Maven 生成 Hibernate 元模型中的 IllegalStateException - 2

    我正在使用hibernate-jpamodelgen通过Maven生成元模型类。当我运行mvncleanpackage时,它工作正常,没有任何问题。但是如果我第二次运行mvnpackage(没有清理),我会得到以下异常:Anexceptionhasoccurredinthecompiler(1.8.0_51).PleasefileabugattheJavaDeveloperConnection(http://java.sun.com/webapps/bugreport)aftercheckingtheBugParadeforduplicates.Includeyourprograman

  9. java - 如何使用 Gradle 5.x 生成 JPA 元模型 - 2

    我目前正在尝试从gradle4.8.1升级到5.1.1,但未能为我们的代码生成hibernate元模型。问题是gradle5忽略了通过编译类路径传递的注释处理器,但我发现的所有插件都在使用它(即“-proc:only”)。我试图明确指定注释处理器,正如gradle(https://docs.gradle.org/4.6/release-notes.html#convenient-declaration-of-annotation-processor-dependencies)所指出的那样annotationProcessor'org.hibernate:hibernate-jpamod

  10. java - Spring:缺少 JPA 元模型 - 2

    我无法理解带有JPA存储库的简单SpringMVC项目出了什么问题。能否给个提示。域:packagecom.test.app;@Entity@Table(name="foo_table")publicclassFooDomain{@Id@Column(name="id",unique=true,nullable=false)privateIntegerid;@Column(name="text",nullable=false)privateStringtext;//getters&settershere...存储库packagecom.test.app;@RepositoryDefin

随机推荐