ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

设计模式结构型——享元模式

设计模式结构型——享元模式 目录什么是享元模式享元模式的实现享元模式角色享元模式类图享元模式代码实现享元模式的特点优点缺点使用场景注意事项什么是享元模式享元模式Flyweight Pattern是一种结构型设计模式享元模式中的“享元”指被共享的单元享元模式通过复用对象以达到节省内存的目的。要求能够共享的对象必须是细粒度对象因此它又称为轻量级模式。其主要解决的问题是创建大量相似对象时的内存开销过大。其意图运用共享技术有效地支持大量细粒度的对象。解决在有大量对象时有可能会造成内存溢出问题把其中共同的部分抽象出来查找时直接返回在内存中已有的对象没有才重新创建避免重新创建已有对象。减少创建对象的数量以减少内存占用和提高性能避免大量相似对象的开销从而提高系统资源的利用率尽可能复用现有的同类对象。“享元”被共享的单元即复用对象节省内存注意前提是享元对象是不可变对象。当一个系统中存在大量重复不可变对象就能利用享元模式将对象设计成享元在内存中只保留一份实例供引用。这就减少内存中对象的数量最终节省内存。当然不仅相同对象可设计成享元相似对象也能提取对象中的相同部分字段设计成享元。“不可变对象”一旦通过构造器初始化完成后其状态对象的成员变量或属性就不会再被修改。所以不可变对象不能暴露任何set()等修改内部状态的方法。之所以要求享元是不可变对象是因为它会被多处代码共享使用避免一处代码对享元进行了修改影响到其他使用它的代码。享元模式的实现享元Flyweight 模式中存在以下两种状态1.内部状态即不会随着环境的改变而改变的可共享部分。2.外部状态指随环境改变而改变的不可以共享的部分。享元模式的实现要领就是区分应用中的这两种状态并将外部状态外部化。享元模式角色抽象享元角色Flyweight通常是一个接口或抽象类在抽象享元类中声明了具体享元类公 共的方法这些方法可以向外界提供享元对象的内部数据内部状态同时也可以通过这些方法来设置外部数据外部状态。具体享元角色Concrete Flyweight实现了抽象享元类称为享元对象在具体享元 类中为内部状态提供了存储空间。通常我们可以结合单例模式来设计具体享元类为每一个具体享元类提供唯一的享元对象。非享元角色Unsharable Flyweight)并非所有的抽象享元类的子类都需要被共享不 能被共享的子类可设计为非共享具体享元类当需要一个非共享具体享元类的对象时可以直接通过实例化创建。享元工厂角色Flyweight Factory负责创建和管理享元角色。当客户对象请求一个享元 对象时享元工厂检査系统中是否存在符合要求的享元对象存在则提供给客户不存在新创建提供给客户。享元模式类图享元模式代码实现抽象享元角色package com.common.demo.pattern.flyweight; /** * author Evan Walker 昂焱数据: https://www.ayshuju.com * version 1.0 * desc 抽象享元角色 篮球 * date 2023/07/21 15:03:57 */ public interface BasketBall { void play(); }具体享元角色和非享元角色package com.common.demo.pattern.flyweight; /** * author Evan Walker 昂焱数据: https://www.ayshuju.com * version 1.0 * desc 具体享元角色 体育馆 * date 2023/07/21 15:05:37 */ public class Gymnasium implements BasketBall{ private String gymnasiumName; private String sport 篮球; double price 50; public Gymnasium() { } public Gymnasium(String gymnasiumName) { this.gymnasiumName gymnasiumName; } public String getGymnasiumName() { return gymnasiumName; } public void setGymnasiumName(String gymnasiumName) { this.gymnasiumName gymnasiumName; } public String getSport() { return sport; } public void setSport(String sport) { this.sport sport; } public double getPrice() { return price; } public void setPrice(double price) { this.price price; } Override public void play() { System.out.println(Gymnasium{ gymnasiumName gymnasiumName \ , sport sport \ , price price } , this Object this \ ); } }享元工厂角色package com.common.demo.pattern.flyweight; import java.util.HashMap; import java.util.Map; import java.util.Objects; /** * author Evan Walker 昂焱数据: https://www.ayshuju.com * version 1.0 * desc 享元工厂 篮球工厂 * date 2023/07/21 15:11:37 */ public class BasketBallFactory { private static MapString,Gymnasium MAP new HashMap(); public static Gymnasium getBasketBall(String gymnasiumName){ Gymnasium gymnasium MAP.get(gymnasiumName); if(Objects.isNull(gymnasium)){ gymnasium new Gymnasium(gymnasiumName); MAP.put(gymnasiumName,gymnasium); } return gymnasium; } }测试类package com.common.demo.pattern.flyweight; import java.util.ArrayList; import java.util.List; /** * author Evan Walker 昂焱数据: https://www.ayshuju.com * version 1.0 * desc * date 2023/07/21 15:16:00 */ public class Test { private static final ListString nameList new ArrayList(); public static void main(String[] args) { nameList.add(斯塔普斯中心球馆); nameList.add(大通中心球馆); nameList.add(麦迪逊花园球馆); nameList.add(联合中心球馆); nameList.add(速贷中心球馆); nameList.add(斯塔普斯中心球馆); nameList.add(速贷中心球馆); nameList.add(美航球馆); nameList.add(丹佛百事中心球馆); for (String name : nameList){ BasketBallFactory.getBasketBall(name).play(); } } }测试截图享元模式的特点优点大大减少对象的创建对象复用降低系统的内存使效率提高。缺点提高了系统的复杂度需要分离出外部状态和内部状态而且外部状态具有固有化的性质不应该随着内部状态的变化而变化否则会造成线程安全问题。需要牺牲一定的时间和空间来实现对象共享和控制机制。当对象之间没有复用性时使用享元模式可能会导致额外的开销。使用场景系统有大量相似对象。当对象需要被共享时如需要缓冲池的场景。当系统的内存资源相对有限时可以考虑使用享元模式以减少内存的使用。当需要减少对象的创建次数、降低系统开销时。注意事项注意划分外部状态和内部状态否则可能会引起线程安全问题。这些类必须有一个工厂对象加以控制。
返回列表