【地铁上的设计模式】--结构型模式:享元模式

2023-05-03 14:35:58 浏览数 (1)

什么是享元模式

享元模式是一种结构型设计模式,旨在通过尽可能多地共享内部状态来最大化共享对象的数量,从而减少系统中对象的数量。这种模式适用于需要创建大量细粒度对象的情况,并且它可以大幅降低内存使用和对象创建的开销。 在享元模式中,对象可以分为两类:内部状态和外部状态。内部状态是可以共享的,通常保存在享元对象内部,并且不会随着时间的推移而改变。而外部状态则是不可共享的,它通常取决于具体场景,并在运行时传递给享元对象。 这种模式的主要思想是在内存中维护一个对象池,用于存储共享的对象。当需要创建对象时,首先从对象池中查找是否已经有该对象的实例存在。如果已经存在,则返回现有实例,否则创建一个新的实例并将其添加到对象池中以供未来使用。 优点包括节省内存,提高性能和可维护性。缺点则是需要对系统进行深入分析和设计,以确定内部状态和外部状态,因此可能会增加系统的复杂性。 享元模式通常和其他设计模式一起使用,例如工厂模式和单例模式,以进一步优化系统性能和可维护性。

如何实现享元模式

享元模式的实现步骤如下:

  1. 定义享元接口:在接口中定义享元类需要实现的方法。
  2. 实现具体的享元类:实现享元接口中定义的方法,并将其内部状态作为类成员变量。
  3. 定义享元工厂类:负责创建和管理享元对象。在工厂类中,通常维护一个享元对象的池子,用于存储已经创建的享元对象。
  4. 使用享元对象:在客户端中,通过享元工厂获取共享对象,然后对其进行操作。

通过使用享元模式,可以减少系统中对象的数量,从而提高系统的性能和可维护性。但是,需要注意的是,享元模式的使用必须满足对象可以共享的条件,即对象中存在一些可以共享的状态。同时,享元模式的实现也会增加系统的复杂性,需要进行权衡和设计。

Java实现 下面是一个简单的 Java 代码示例,展示了如何实现享元模式:

代码语言:javascript复制
import java.util.HashMap;

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

    public Flyweight getFlyweight(String key) {
        if (flyweights.containsKey(key)) {
            return flyweights.get(key);
        } else {
            Flyweight flyweight = new ConcreteFlyweight(key);
            flyweights.put(key, flyweight);
            return flyweight;
        }
    }
}

public interface Flyweight {
    public void operation();
}

public class ConcreteFlyweight implements Flyweight {
    private String key;

    public ConcreteFlyweight(String key) {
        this.key = key;
        System.out.println("ConcreteFlyweight "   key   " created");
    }

    public void operation() {
        System.out.println("ConcreteFlyweight "   key   " operation");
    }
}

public class Client {
    public static void main(String[] args) {
        FlyweightFactory factory = new FlyweightFactory();
        Flyweight flyweight1 = factory.getFlyweight("key1");
        Flyweight flyweight2 = factory.getFlyweight("key1");

        flyweight1.operation();
        flyweight2.operation();

        System.out.println(flyweight1 == flyweight2);
    }
}

在上面的示例中,FlyweightFactory 是一个工厂类,用于创建和管理享元对象。Flyweight 接口是享元对象的基类,定义了它们的共同操作。ConcreteFlyweight 是实际的享元对象,实现了 Flyweight 接口中定义的操作。Client 类是一个使用享元模式的示例,它创建了两个具有相同 keyFlyweight 对象,并执行它们的操作。由于这两个对象具有相同的 key,因此它们是同一个对象,这也反映了享元模式的一个重要特点:相同的对象只会被创建一次,然后可以被多个客户端共享。

C#实现 以下是 C# 中实现享元模式的示例代码:

代码语言:javascript复制
using System;
using System.Collections.Generic;

// 定义享元接口
interface IFlyweight
{
    void Operation();
}

// 实现享元类
class ConcreteFlyweight : IFlyweight
{
    private string intrinsicState;

    public ConcreteFlyweight(string state)
    {
        this.intrinsicState = state;
    }

    public void Operation()
    {
        Console.WriteLine("ConcreteFlyweight: "   this.intrinsicState);
    }
}

// 实现享元工厂类
class FlyweightFactory
{
    private Dictionary<string, IFlyweight> flyweights = new Dictionary<string, IFlyweight>();

    public IFlyweight GetFlyweight(string key)
    {
        if (flyweights.ContainsKey(key))
        {
            return flyweights[key];
        }
        else
        {
            IFlyweight flyweight = new ConcreteFlyweight(key);
            flyweights.Add(key, flyweight);
            return flyweight;
        }
    }
}

// 客户端代码
class Client
{
    static void Main(string[] args)
    {
        FlyweightFactory factory = new FlyweightFactory();
        IFlyweight flyweight1 = factory.GetFlyweight("A");
        IFlyweight flyweight2 = factory.GetFlyweight("B");
        IFlyweight flyweight3 = factory.GetFlyweight("A");

        flyweight1.Operation();
        flyweight2.Operation();
        flyweight3.Operation();

        Console.ReadKey();
    }
}

以上代码定义了享元接口 IFlyweight,以及实现了具体享元类 ConcreteFlyweight 和享元工厂类 FlyweightFactory。客户端通过享元工厂类获取具体享元类的实例,并调用其 Operation() 方法。

总结

享元模式是一种结构型设计模式,它通过共享具有相同状态的对象来尽量减少内存使用和对象创建的数量。这种模式的主要思想是将可共享的状态和不可共享的状态分开处理,减少重复对象的创建,从而降低系统的内存压力和提升性能。 优点:享元模式可以减少对象的创建数量,从而减少了内存的占用,提高了系统的性能。同时,由于享元对象是共享的,可以减少对外部资源的依赖,提高系统的稳定性和安全性。 缺点:享元模式的实现比较复杂,需要考虑对象的状态和非共享的状态。同时,由于对象的状态被共享,可能会导致共享对象的变化会影响到其他对象的状态,需要考虑多线程并发访问的问题。 总之,享元模式适用于需要创建大量重复对象的场景,可以减少系统的内存开销和提高系统的性能。但是需要注意对共享对象的状态进行维护和管理,避免出现多线程并发访问的问题。

0 人点赞