专注于 JetBrains IDEA 全家桶,永久激活,教程
持续更新 PyCharm,IDEA,WebStorm,PhpStorm,DataGrip,RubyMine,CLion,AppCode 永久激活教程

享元模式

享元模式(Flyweight),使用共享技术有效地支持大量细粒度的对象。常用于系统底层开发,解决系统的性能问题。比如,数据库连接池技术。

享元模式能够解决重复对象的内存浪费的问题,当系统中有大量相似对象,需要缓冲池时,不需总是创建新对象,可以从缓冲池里获取。这样可以降低系统内存消耗,同时提高效率。

享元模式经典的应用场景就是池技术了,String 常量池、数据库连接池、缓冲池等等都是享元模式的应用,它是池技术的重要实现方式。

要应用享元模式,我们需要将对象属性分为内部属性和外部属性。内部属性使对象唯一,而外部属性由客户端代码设置并用于执行不同的操作。

享元模式解析

75_1.png

角色介绍

  • Flyweight:它是所有具体享元类的超类或接口,通过这个接口,Flyweight 可以接受并作用于外部状态。
  • ConcreteFlyweight:它是继承 Flyweight 超类或实现 Flyweight 接口,并为内部状态增加存储空间。
  • UnsharedConcreteFlyweight:它是指那些不需要共享的Flyweight子类。因为 Flyweight 接口共享成为可能,但它并不强制共享。
  • FlyweightFactory:它是一个享元工厂,用来创建并管理 Flyweight 对象.它主要是用来确保合理地共享 Flyweight ,当用户请求一个 Flyweight 时,Flywei ghtFactory 对象提供一个 已创建的实例或者创建一个(如果不存在的话)。

享元模式基本代码

  • Flyweight 类
public interface Flyweight {

    void operation(int status);
}

  • ConcreteFlyweight 类
public class ConcreteFlyweight implements Flyweight {

    @Override
    public void operation(int status) {
        System.out.println("具体的 Flyweight: " + status);
    }
}

  • UnshareConcreteFlyweight 类
public class UnshareConcreteFlyweight implements Flyweight {

    @Override
    public void operation(int status) {
        System.out.println("不共享的具体Flyweight: " + status);
    }
}

  • FlyweightFactory 类
public class FlyweightFactory {

    private static Map<String, Flyweight> flyweightMap = new HashMap<>();

    private FlyweightFactory() {

    }

    public static Flyweight getFlyweight(String key) {
        Flyweight flyweight = flyweightMap.get(key);
        if (flyweight == null) {
            if (Objects.equals(key, "A")) {
                flyweight = new ConcreteFlyweight();
            }

            if (Objects.equals(key, "B")) {
                flyweight = new ConcreteFlyweight();
            }
            flyweightMap.put(key, flyweight);
        }

        return flyweight;
    }

}

  • Client 类
public class Client {

    public static void main(String[] args) {
        // 外部状态
        int status = 2;
        Flyweight flyweightA = FlyweightFactory.getFlyweight("A");
        flyweightA.operation(status);

        Flyweight flyweightB = FlyweightFactory.getFlyweight("B");
        flyweightB.operation(status + 1);

        // 不共享的 Flyweight
        UnshareConcreteFlyweight unshareConcreteFlyweight = new UnshareConcreteFlyweight();
        unshareConcreteFlyweight.operation(status + 2);

    }
}

示例

假设我们需要使用线条和椭圆形创建图形。因此,我们将有一个接口 Shape 和它的具体实现为 Line 和 Oval。椭圆类将具有固有属性,以确定是否用给定的颜色填充椭圆,而 Line 将不具有任何固有属性。

使用享元模式实现

  • Shape 类
public interface Shape {

    public void draw(int x, int y, int width, int height, Color color);
}

  • Line 类
public class Line implements Shape {

    public Line(){
        System.out.println("Creating Line object");
    }

    @Override
    public void draw(int x1, int y1, int x2, int y2,
            Color color) {
            System.out.println("Draw Line");
    }

}

  • Oval 类
public class Oval implements Shape {

    // 内部属性
    private boolean fill;

    public Oval(boolean isFill){
        this.fill = fisFill;
        System.out.println("Creating Oval object");
    }
    @Override
    public void draw(int x, int y, int width, int height,
            Color color) {
        System.out.println("Draw Oval");
        if(fill){
            System.out.println("Fill Oval with color");
        }
    }
}

  • ShapeFactory 类
public class ShapeFactory {

    private static final Map<ShapeType,Shape> shapes = new HashMap<ShapeType,Shape>();

    public static Shape getShape(ShapeType type) {
        Shape shape = shapes.get(type);

        if (shape == null) {
            if (type.equals(ShapeType.OVAL_FILL)) {
                shape = new Oval(true);
            } else if (type.equals(ShapeType.OVAL_NOFILL)) {
                shape = new Oval(false);
            } else if (type.equals(ShapeType.LINE)) {
                shape = new Line();
            }
            shapes.put(type, shape);
        }
        return shape;
    }

    public static enum ShapeType{
        OVAL_FILL, OVAL_NOFILL, LINE;
    }
}

  • Client 类
public class Client {

  public static void main(String[] args) {
    Shape shape = ShapeFactory.getShape(ShapeType.LINE);
    // 伪代码
    shape.draw(x1, y1, x2, y2);

    Shape shape1 = ShapeFactory.getShape(ShapeType.LINE);
    // 伪代码
    shape1.draw(x1, y1, x2, y2);
  }
}

当我们多次创建 Line 图形时,由于程序使用了共享库,因此程序将快速执行。

小结

当我们需要创建一个类的许多对象且没有足够的内存容量时,可以使用享元模式。由于每个对象都会占用至关重要的内存空间,因此可以应用享元模式来通过共享对象来减少内存负载,同时也能提高程序效率。

事实上,享元模式可以避免大量非常相似类的开销。在程序设计中,有时需要生成大量细粒度的类实例来表示数据。如果能发现这些实例除了几个参数外基本上都是相同的,有时就能够受大幅度地减少需要实例化的类的数量。如果能把那些参数移到类实例的外面,在方法调用时将它们传递进来,就可以通过共享大幅度地减少单个实例的数目。

未经允许不得转载:搜云库技术团队 » 享元模式

JetBrains 全家桶,激活、破解、教程

提供 JetBrains 全家桶激活码、注册码、破解补丁下载及详细激活教程,支持 IntelliJ IDEA、PyCharm、WebStorm 等工具的永久激活。无论是破解教程,还是最新激活码,均可免费获得,帮助开发者解决常见激活问题,确保轻松破解并快速使用 JetBrains 软件。获取免费的破解补丁和激活码,快速解决激活难题,全面覆盖 2024/2025 版本!

联系我们联系我们