跳到主要内容

12、C#设计模式 - 享元模式

享元模式(Flyweight Pattern)

享元模式属于结构型模式,它以共享的方式高效的支持大量的细粒度对象。通过复用内存中已存在的对象,降低系统创建对象实例的性能消耗。

享元模式尝试重用现有的同类对象,如果未找到匹配的对象,则创建新对象,如果找到对象,则直接返回。

角色:

1、 抽象享元(Flyweight);

它是所有具体享元类的抽象基类,为其子类规定出需要实现的公共接口;

2、 具体享元(ConcreteFlyweight);

具体享元类实现了抽象享元类所规定的接口;

3、 享元工厂(FlyweightFactoiy);

享元工厂类负责创建和管理享元对象。

示例:

 

命名空间FlyweightPattern中包含IConnection接口充当抽象享元,Connection类充当具体享元,ConnectionFactory工厂类充当享元工厂。本案例通过使用享元模式来共享数据库连接。

namespace FlyweightPattern
public interface IConnection {

    void Print();

}

IConnection接口,包含一个打印的方法。

public class Connection : IConnection {

    private string _connectionString = null;

    public Connection(string connectionString) {
        _connectionString = connectionString;
        Thread.Sleep(1000);
        Console.WriteLine("It took 1 second(s) to create a connection!");
    }

    public void Print() {
        Console.WriteLine($"Database connection is {_connectionString}");
        Console.WriteLine("-------------------------------------------------------");
    }

}

Connection类,定义数据库连接(演示)。

public class ConnectionFactory {

    private Dictionary<string, IConnection> _connections = null;

    private string _connectionString = null;

    public ConnectionFactory() {
        _connections = new Dictionary<string, IConnection>();
    }

    public IConnection CreateConnection(string connectionString) {
        if (!_connections.ContainsKey(connectionString)) {
            Console.WriteLine("Creating a new connection!");
            IConnection connection = new Connection(connectionString);
            _connections.Add(connectionString, connection);
            return connection;
        }
        else {
            Console.WriteLine("Return an exist connection!");
            var connection = _connections[connectionString] as IConnection;
            return connection;
        }
    }

}

ConnectionFactory类,数据库连接工厂,内部维持对所有连接的引用,CreateConnection方法在发现连接存在时直接返回,如果不存在,则创建一个新的连接并维持进列表。

注:实际开发过程中应该用HashCode来检索数据库连接是否存在。

public class Program {

    private static ConnectionFactory _factory = null;

    private static List<string> _connections = null;

    private static IConnection _connection = null;

    private static void Print(int index) {
        if (index > _connections.Count - 1) {
            Console.WriteLine("Index Out Of Range Exception!");
            return;
        }
        _connection = _factory.CreateConnection(_connections[index]);
        _connection.Print();
    }

    public static void Main(string[] args) {
        _connections = new List<string> {
            "Server=Aron1;Database=pubs;\n" + "Uid=uid;Pwd=password;",
            "Provider=sqloledb;Data Source=Aron1;\n" + "User Id=uid;Password=password;",
            "Data Source=192.168.0.1,1433;\n" + "UserID=uid;Password=password;"
        };

        _factory = new ConnectionFactory();

        Print(0);
        Print(1);
        Print(2);
        Print(1);
        Print(3);

        Console.ReadKey();
    }

}

以上是调用方的代码,以下是这个案例的输出结果:

Creating a new connection!
It took 1 second(s) to create a connection!
Database connection is Server=Aron1;Database=pubs;
Uid=uid;Pwd=password;
-------------------------------------------------------
Creating a new connection!
It took 1 second(s) to create a connection!
Database connection is Provider=sqloledb;Data Source=Aron1;
User Id=uid;Password=password;
-------------------------------------------------------
Creating a new connection!
It took 1 second(s) to create a connection!
Database connection is Data Source=192.168.0.1,1433;
UserID=uid;Password=password;
-------------------------------------------------------
Return an exist connection!
Database connection is Provider=sqloledb;Data Source=Aron1;
User Id=uid;Password=password;
-------------------------------------------------------
Index Out Of Range Exception!

优点:

1、 降低了系统中对象的数量,从而降低了系统中细粒度对象给内存带来的压力;

缺点:

1、 为了使对象可以共享,需要将一些状态外部化,这使得程序的逻辑更复杂,使系统复杂化;
2、 享元模式将享元对象的状态外部化,而读取外部状态使得运行时间稍微变长;

使用场景:

1、 一个系统中有大量的对象;
2、 这些对象耗费大量的内存;
3、 这些对象中的状态大部分都可以被外部化;
4、 这些对象可以按照内部状态分成很多的组,当把外部对象从对象中剔除时,每一个组都可以仅用一个对象代替;
5、 软件系统不依赖这些对象的身份;