Java设计模式--享元模式

简介: 享元模式运用共享技术有效的支持大量细粒度的对象。Flyweight PatternUse sharing to support large numbers of fine-grained objects efficiently.类图模式的结构与使用享元方法模式的结构中包括三种角色。 + 享元接口(Flyweight):是一个接口,该接

享元模式

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

Flyweight Pattern

Use sharing to support large numbers of fine-grained objects efficiently.

类图

模式的结构与使用

享元方法模式的结构中包括三种角色。
+ 享元接口(Flyweight):是一个接口,该接口定义了享元对外公开其内部数据的方法,以及享元接收外部数据的方法。
+ 具体享元(Concrete Flyweight):实现享元接口的类,该类的实例称为享元对象,或简称享元。具体享元类的成员变量为享元对象的内部状态,享元对象的内部状态必须与所处的周围环境无关,即要保证使用享元对象的应用程序无法更改享元的内部状态,只有这样才能使得享元对象在系统中被共享。因为享元对象是用来共享的,所以不能允许用户各自地使用具体享元类来创建对象,这样就无法达到共享的目的,因为不同用户用具体享元类创建的对象显然是不同的,所以,具体享元类的构造方法必须是private的,其目的是不允许用户程序直接使用具体享元类来创建享元对象,创建和管理享元对象由享元工厂负责。
+ 享元工厂(Flyweight Factory):享元工厂是一个类,该类的实例负责创建和管理享元对象,用户或其他对象必须请求享元工厂为它得到一个享元对象。享元工厂可以通过一个散列表(也称共享池)来管理享元对象,当用户程序或其他若干个对象向享元工厂请求一个享元对象时,如果享元工厂的散列表中已有这样的享元对象,享元工厂就提供这个享元对象给请求者,否则就创建一个享元对象添加到散列表中,同时该享元对象提供给请求者。显然,当若干个用户或对象请求享元工厂提供一个享元对象时,第一个用户获得该享元对象的时间可能慢一些,但是后继的用户会较快地获得这个享元对象。可以使用单例模式来设计享元工厂,即让系统中只有一个享元工厂的实例。另外,为了让享元工厂能生成享元对象,需要将具体享元类作为享元工厂的内部类。

简单的例子

Flyweight的抽象类Flyweight.java

package Flyweight;

public interface Flyweight {
    public double getHeight();      //返回内部数据
    public double getWidth();
    public double getLength();
    public void printMess(String mess);  //使用参数mess获取外部数据
}

Flyweight Factory的实现类FlyweightFactory.java

package Flyweight;

import java.util.HashMap;

public class FlyweightFactory {
    private HashMap<String, Flyweight> hashMap;
    static FlyweightFactory factory = new FlyweightFactory();

    public FlyweightFactory() {
        this.hashMap = new HashMap<String, Flyweight>();
    }

    public static FlyweightFactory getFactory() {
        return factory;
    }

    public synchronized Flyweight getFlyweight(String key) {
        if (hashMap.containsKey(key)) {
            return hashMap.get(key);
        } else {
            double width = 0,height = 0,lenght = 0;
            String[] str = key.split("#");
            width = Double.parseDouble(str[0]);
            height = Double.parseDouble(str[1]);
            lenght = Double.parseDouble(str[2]);
            Flyweight ft = new ConcreteFlyweight(width, height, lenght);
            hashMap.put(key, ft);
            return ft;
        }
    }

    class ConcreteFlyweight implements Flyweight {

        private double width;
        private double height;
        private double lenght;


        public ConcreteFlyweight(double width, double height, double lenght) {
            this.width = width;
            this.height = height;
            this.lenght = lenght;
        }

        @Override
        public double getHeight() {
            return height;
        }

        @Override
        public double getWidth() {
            return width;
        }

        @Override
        public double getLength() {
            return lenght;
        }

        @Override
        public void printMess(String mess) {
            System.out.println(mess);
            System.out.print("宽度:" + width);
            System.out.print("高度:" + height);
            System.out.print("长度:" + lenght);
        }

    }
}

需要使用共享数据的类Car.java

package Flyweight;

public class Car {
    Flyweight flyweight;
    String name, color;
    int power;

    public Car(Flyweight flyweight, String name, String color, int power) {
        this.flyweight = flyweight;
        this.name = name;
        this.color = color;
        this.power = power;
    }

    public void print() {
        System.out.println("名称:" + name);
        System.out.println("颜色:" + color);
        System.out.println("功率:" + power);
        System.out.println("宽度:" + flyweight.getWidth());
        System.out.println("高度:" + flyweight.getHeight());
        System.out.println("长度:" + flyweight.getLength());
    }

}

测试类Application.java

package Flyweight;

public class Application {

    public static void main(String[] args) {
        FlyweightFactory factory = FlyweightFactory.getFactory();
        double width = 1.82, height = 1.47, lenght = 5.12;
        String key = "" + width + "#" + height + "#" + lenght;
        Flyweight flyweight = factory.getFlyweight(key);
        Car audiA60ne = new Car(flyweight, "奥迪A6", "黑色", 128);
        Car audiA6Two = new Car(flyweight, "奥迪A6", "灰色", 160);
        //audiA60ne和audiA6Two没有向享元传递外部数据,而是获取享元的内部数据
        audiA60ne.print();
        audiA6Two.print();
        width = 1.77;
        height = 1.45;
        lenght = 4.63;
        key = "" + width + "#" + height + "#" + lenght;
        Car audiA40ne = new Car(flyweight, "奥迪A4", "蓝色", 126);
        Car audiA4Two = new Car(flyweight, "奥迪A4", "红色", 138);
        //audiA40ne和audiA4Two向享元传递外部数据,这些数据是不共享的
        flyweight.printMess("名称: 奥迪A4 颜色:蓝色 功率:126");
        flyweight.printMess("名称: 奥迪A4 颜色:红色 功率:138");
    }
}

执行结果

享元模式的优点

  • 使用享元模式可以节省内存的开销,特别适合处理大量细粒度对象,这些对象的许多属性值是相同的,而且一旦创建则不容许修改。
  • 享元模式中的享元可以使用方法的参数接收外部状态中的数据,但外部状态数据不会干扰到享元中的内部数据,这就使享元可以在不同的环境中被共享。

适用享元模式的情景

下列情况之一就可以考虑使用享元模式:

  • 一个应用程序使用大量的对象,这些对象之间部分属性本质上是相同的,这时应使用享元来封装相同的部分。
  • 对象的多数状态都可变为外部状态,就可以考虑将这些对象作为系统中的享元来使用。

下载源码请到

MyGitHub

目录
相关文章
|
2月前
|
设计模式 Java Spring
Java 设计模式之责任链模式:优雅处理请求的艺术
责任链模式通过构建处理者链,使请求沿链传递直至被处理,实现发送者与接收者的解耦。适用于审批流程、日志处理等多级处理场景,提升系统灵活性与可扩展性。
247 2
|
2月前
|
设计模式 网络协议 数据可视化
Java 设计模式之状态模式:让对象的行为随状态优雅变化
状态模式通过封装对象的状态,使行为随状态变化而改变。以订单为例,将待支付、已支付等状态独立成类,消除冗长条件判断,提升代码可维护性与扩展性,适用于状态多、转换复杂的场景。
281 0
|
4月前
|
设计模式 缓存 Java
Java设计模式(二):观察者模式与装饰器模式
本文深入讲解观察者模式与装饰器模式的核心概念及实现方式,涵盖从基础理论到实战应用的全面内容。观察者模式实现对象间松耦合通信,适用于事件通知机制;装饰器模式通过组合方式动态扩展对象功能,避免子类爆炸。文章通过Java示例展示两者在GUI、IO流、Web中间件等场景的应用,并提供常见陷阱与面试高频问题解析,助你写出灵活、可维护的代码。
|
2月前
|
设计模式 算法 搜索推荐
Java 设计模式之策略模式:灵活切换算法的艺术
策略模式通过封装不同算法并实现灵活切换,将算法与使用解耦。以支付为例,微信、支付宝等支付方式作为独立策略,购物车根据选择调用对应支付逻辑,提升代码可维护性与扩展性,避免冗长条件判断,符合开闭原则。
280 35
|
2月前
|
设计模式 消息中间件 传感器
Java 设计模式之观察者模式:构建松耦合的事件响应系统
观察者模式是Java中常用的行为型设计模式,用于构建松耦合的事件响应系统。当一个对象状态改变时,所有依赖它的观察者将自动收到通知并更新。该模式通过抽象耦合实现发布-订阅机制,广泛应用于GUI事件处理、消息通知、数据监控等场景,具有良好的可扩展性和维护性。
241 8
|
7月前
|
设计模式 存储 缓存
【设计模式】【结构型模式】享元模式(Flyweight)
一、入门 什么是享元模式? 享元模式(Flyweight Pattern)是一种结构型设计模式,旨在通过共享对象来减少内存使用,特别适用于存在大量相似对象的情况。 它的核心思想是将对象的内在状态(不变
252 16
|
7月前
|
设计模式 缓存 安全
【高薪程序员必看】万字长文拆解Java并发编程!(8):设计模式-享元模式设计指南
🌟 ​大家好,我是摘星!​ 🌟今天为大家带来的是并发编程中的经典对象复用设计模式-享元模式,废话不多说让我们直接开始。
167 0
|
4月前
|
设计模式 安全 Java
Java设计模式(一):单例模式与工厂模式
本文详解单例模式与工厂模式的核心实现及应用,涵盖饿汉式、懒汉式、双重检查锁、工厂方法、抽象工厂等设计模式,并结合数据库连接池与支付系统实战案例,助你掌握设计模式精髓,提升代码专业性与可维护性。
|
4月前
|
设计模式 XML 安全
Java枚举(Enum)与设计模式应用
Java枚举不仅是类型安全的常量,还具备面向对象能力,可添加属性与方法,实现接口。通过枚举能优雅实现单例、策略、状态等设计模式,具备线程安全、序列化安全等特性,是编写高效、安全代码的利器。
|
10月前
|
设计模式 存储 缓存
「全网最细 + 实战源码案例」设计模式——享元模式
享元模式(Flyweight Pattern)是一种结构型设计模式,旨在减少大量相似对象的内存消耗。通过分离对象的内部状态(可共享、不变)和外部状态(依赖环境、变化),它有效减少了内存使用。适用于存在大量相似对象且需节省内存的场景。模式优点包括节省内存和提高性能,但会增加系统复杂性。实现时需将对象成员变量拆分为内在和外在状态,并通过工厂类管理享元对象。
361 92