zoukankan      html  css  js  c++  java
  • 设计模式学习总结享元模式(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:
    享元工厂中维护了享元实例的列表,同样也需要占用资源,所以如果享元的实例不是非常多的话(一个对象的应用场景比较少),不适合使用享元模式
    如果对象拥有非常多的独立状态,比共享状态还要多不适合运用享元模式。因为维持大量的外部状态不但会使逻辑复杂而且并不能节约资源。

  • 相关阅读:
    为什么我的从任务管理器中看见我的硬盘使用率是100%(2)
    为什么我的从任务管理器中看见我的硬盘使用率是100%(1)
    win8正式版
    pwnable_orw
    cmcc_simplerop
    分析kernel.dll函数CreateRemoteThread进0环
    [V&N2020 公开赛]easyTHeap
    恶意代码分析训练第一天
    SWPUCTF_2019_p1KkHeap
    3环函数进入0环函数
  • 原文地址:https://www.cnblogs.com/ejiyuan/p/2612198.html
Copyright © 2011-2022 走看看