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

简介: 【愚公系列】2021年12月 二十三种设计模式(十一)-享元模式(Flyweight Pattern)

文章目录

前言

一、享元模式(Flyweight Pattern)

二、使用步骤

角色

示例

总结

优点

缺点

使用场景

前言

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


提示:以下是本篇文章正文内容,下面案例可供参考


一、享元模式(Flyweight Pattern)

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


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


二、使用步骤

角色

1、抽象享元(Flyweight)


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


2、具体享元(Concrete Flyweight)


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


3、享元工厂(FlyweightFactoiy)


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


示例

image.png

命名空间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!

总结

优点

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


缺点

1、为了使对象可以共享,需要将一些状态外部化,这使得程序的逻辑更复杂,使系统复杂化;

2、享元模式将享元对象的状态外部化,而读取外部状态使得运行时间稍微变长。


使用场景

1、一个系统中有大量的对象;

2、这些对象耗费大量的内存;

3、这些对象中的状态大部分都可以被外部化;

4、这些对象可以按照内部状态分成很多的组,当把外部对象从对象中剔除时,每一个组都可以仅用一个对象代替;

5、软件系统不依赖这些对象的身份。


相关文章
|
1月前
|
设计模式 存储 缓存
「全网最细 + 实战源码案例」设计模式——享元模式
享元模式(Flyweight Pattern)是一种结构型设计模式,旨在减少大量相似对象的内存消耗。通过分离对象的内部状态(可共享、不变)和外部状态(依赖环境、变化),它有效减少了内存使用。适用于存在大量相似对象且需节省内存的场景。模式优点包括节省内存和提高性能,但会增加系统复杂性。实现时需将对象成员变量拆分为内在和外在状态,并通过工厂类管理享元对象。
166 92
|
6月前
|
设计模式 Java
Java设计模式-享元模式(12)
Java设计模式-享元模式(12)
|
6月前
|
设计模式
设计模式-工厂模式 Factory Pattern(简单工厂、工厂方法、抽象工厂)
这篇文章详细解释了工厂模式,包括简单工厂、工厂方法和抽象工厂三种类型。每种模式都通过代码示例展示了其应用场景和实现方法,并比较了它们之间的差异。简单工厂模式通过一个工厂类来创建各种产品;工厂方法模式通过定义一个创建对象的接口,由子类决定实例化哪个类;抽象工厂模式提供一个创建相关或依赖对象家族的接口,而不需要明确指定具体类。
设计模式-工厂模式 Factory Pattern(简单工厂、工厂方法、抽象工厂)
|
7月前
|
设计模式 存储 Java
【十】设计模式~~~结构型模式~~~享元模式(Java)
文章详细介绍了享元模式(Flyweight Pattern),这是一种对象结构型模式,通过共享技术实现大量细粒度对象的重用,区分内部状态和外部状态来减少内存中对象的数量,提高系统性能。通过围棋棋子的设计案例,展示了享元模式的动机、定义、结构、优点、缺点以及适用场景,并探讨了单纯享元模式和复合享元模式以及与其他模式的联用。
【十】设计模式~~~结构型模式~~~享元模式(Java)
|
6月前
|
设计模式 Java
设计模式--适配器模式 Adapter Pattern
这篇文章介绍了适配器模式,包括其基本介绍、工作原理以及类适配器模式、对象适配器模式和接口适配器模式三种实现方式。
|
8月前
|
设计模式 存储 JavaScript
js设计模式【详解】—— 享元模式
js设计模式【详解】—— 享元模式
89 6
|
9月前
|
设计模式 缓存 Java
Java设计模式:享元模式实现高效对象共享与内存优化(十一)
Java设计模式:享元模式实现高效对象共享与内存优化(十一)
|
9月前
|
设计模式 存储 Java
Java设计模式之享元模式详解
Java设计模式之享元模式详解
|
10月前
|
设计模式 安全 Java
【设计模式】JAVA Design Patterns——Curiously Recurring Template Pattern(奇异递归模板模式)
该文介绍了一种C++的编程技巧——奇异递归模板模式(CRTP),旨在让派生组件能继承基本组件的特定功能。通过示例展示了如何创建一个`Fighter`接口和`MmaFighter`类,其中`MmaFighter`及其子类如`MmaBantamweightFighter`和`MmaHeavyweightFighter`强制类型安全,确保相同重量级的拳手之间才能进行比赛。这种设计避免了不同重量级拳手间的错误匹配,编译时会报错。CRTP适用于处理类型冲突、参数化类方法和限制方法只对相同类型实例生效的情况。
|
9月前
|
设计模式
设计模式-05建造者模式(Builder Pattern)
设计模式-05建造者模式(Builder Pattern)

热门文章

最新文章