设计模式学习总结-享元模式(Flyweight Method)

问题:
在面向对象的设计中和开发中,经常会遇到,同一类型的对象(由同一个class new出)会在不同的场景中出现多次,可是由于应用场景不同,他们的状态(属性值)又有所不同,但是他们的大多数属性又都是相同的,我们需要在不同的应用场景中创建大量具有不同状态的对象,然而大量的对象会造成很大的系统存储开销,以及对象的创建时的性能开销。
定义:

享元模式(又叫:轻量级模式)是一种结构型模式,运用共享技术有效地支持大量细粒度的对象。

意图:
抽出多个同一对象在不同应用场景中的共同状态(intrinsic,在不同的应用场景中相对不变的),封装在一个可以被共享的元类中(Concrete Flyweight),并提供一个修改需要变化状态的访问接口,用于在不同场景中,修改不被共享的外部状态(extrinsic),Flyweight Factory拥有一个管理、存储对象的“仓库”(或者叫对象池),当接收到客户端请求时会遍历对象池中的对象,如果已经存在则直接返回给Client,否则创建一个新的对象并将这个对象加入到池中然后返回给客户端,从而减少了大量的对象创建工作。

参与者:
•抽象享元(Flyweight)角色:

此角色是所有的具体享元类的基类,为这些类规定出需要实现的公共接口。那些需要外部状态(extrinsic)的操作可以通过调用享元方法以参数形式传入。
•具体享元(Concrete Flyweight)角色:

实现抽象享元角色所规定的接口。如果有内部状态(intrinsic)的话,必须负责为内部状态(intrinsic)提供存储空间。享元对象的内部状态(intrinsic)必须与对象所处的周围环境无关,从而使得享元对象可以在系统内共享的。
•享元工厂(Flyweight Factory)角色:

本角色负责创建和管理享元角色。本角色必须保证享元对象可以被系统适当地共享。当一个客户端对象调用一个享元对象的时候,享元工厂角色会检查系统中是否已经有一个符合要求的享元对象。如果已经有了,享元工厂角色就应当提供这个已有的享元对象;如果系统中没有一个适当的享元对象的话,享元工厂角色就应当创建一个合适的享元对象。
•客户端(Client)角色:

本角色需要维护一个对所有享元对象的引用。本角色需要自行存储所有享元对象的外部状态(Extrinsic)。

UML:


实例说明:

诺基亚手机工厂
有总部工厂生产,然后转给各个分公司贴牌上市

uml图如下:

 

代码:

复制代码
/// <summary>
/// 抽象享元(Flyweight)角色
/// </summary>
public abstract class PhoneModel
{

    // 共享元素
    public string Name { getset; }
    public string Net { getset; }
    public string Size { getset; }
    //不共享状态的元素   
    protected string ProductionPlace { getset; }
    // 提供一个修改不共享状态修改的方法。
    public abstract void Change(string productionPlace);
}
/// <summary>
/// 具体享元(Concrete Flyweight)角色
/// </summary>
public class N8Object : PhoneModel
{
    public  N8Object()
    {
        this.Name = "N8";
        this.Net = "CDMA";
        this.Size = "98*20*10";
    }
    public override void Change(string productionPlace)
    {
        this.ProductionPlace = productionPlace;
    }
}
/// <summary>
/// 具体享元(Concrete Flyweight)角色
/// </summary>
public class N9Object : PhoneModel
{
    public  N9Object()
    {
        this.Name = "N9";
        this.Net = "WCDMA";
        this.Size = "100*20*10";
    }
    public override void Change(string productionPlace)
    {
        this.ProductionPlace = productionPlace;
        System.Console.WriteLine("已修改N9的产地为" + productionPlace);
    }
}
/// <summary>
/// 享元工厂(Flyweight Factory)角色
/// </summary>
public class FlyweightFactory 
{
    Dictionary<string, PhoneModel> PhoneList = new Dictionary<string, PhoneModel>();

    public PhoneModel GetPhoneObject(string name)
    {
        if (!PhoneList.ContainsKey(name))
        {
            PhoneModel phone = null;
            switch (name)
            {
                case "N8":
                    phone = new N8Object(); break;
                case "N9":
                    phone = new N9Object(); break;
            }
            PhoneList.Add(name, phone);
        }
        return PhoneList[name];
    }
}
/// <summary>
/// 客户端测试
/// </summary>
public void DecoratorTest()
{
    FlyweightFactory factory = new FlyweightFactory();
    var n8= factory.GetPhoneObject("N8");
    n8.Change("新西兰");
}
复制代码

优点:
•减少处理的对象数量,从而减少大量的对象存储开销,以及对象的创建时的性能开销。
缺点:
•需要由客户端维护对象的外部状态,如果外部状态的数据量大,传递、查找、计算会变得非常复杂。
适用场合:
•系统需要存在大量的对象而不同场景下的对象拥有大量的共享状态。
PS:
享元工厂中维护了享元实例的列表,同样也需要占用资源,所以如果享元的实例不是非常多的话(一个对象的应用场景比较少),不适合使用享元模式
如果对象拥有非常多的独立状态,比共享状态还要多不适合运用享元模式。因为维持大量的外部状态不但会使逻辑复杂而且并不能节约资源。

posted @   ejiyuan  阅读(1699)  评论(3编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· [AI/GPT/综述] AI Agent的设计模式综述
点击右上角即可分享
微信分享提示