写点什么

【愚公系列】2022 年 05 月 二十三种设计模式 (十一)- 享元模式 (Flyweight Pattern)

作者:愚公搬代码
  • 2022 年 5 月 11 日
  • 本文字数:2601 字

    阅读完需:约 9 分钟

前言

设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。 毫无疑问,设计模式于己于他人于系统都是多赢的,设计模式使代码编制真正工程化,设计模式是软件工程的基石,如同大厦的一块块砖石一样。项目中合理的运用设计模式可以完美的解决很多问题,每种模式在现在中都有相应的原理来与之对应,每一个模式描述了一个在我们周围不断重复发生的问题,以及该问题的核心解决方案,这也是它能被广泛应用的原因。

一、享元模式(Flyweight Pattern)

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


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

二、使用步骤

角色

1、抽象享元(Flyweight)


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


2、具体享元(Concrete Flyweight)


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


3、享元工厂(FlyweightFactoiy)


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

示例


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


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!
复制代码


<hr style=" border:solid; width:100px; height:1px;" color=#000000 size=1">

总结

优点

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

缺点

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

使用场景

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

发布于: 刚刚阅读数: 3
用户头像

还未添加个人签名 2022.03.01 加入

该博客包括:.NET、Java、前端、IOS、Android、鸿蒙、Linux、物联网、网络安全、python、大数据等相关使用及进阶知识。查看博客过程中,如有任何问题,皆可随时沟通。

评论

发布
暂无评论
【愚公系列】2022年05月 二十三种设计模式(十一)-享元模式(Flyweight Pattern)_5月月更_愚公搬代码_InfoQ写作社区