• 元对象我所理解的设计模式(C++实现)——享元模式(Flyweight Pattern)


    这段时间个人几篇文章介绍了改元对象的文章. 关联文章的地址

        

    概述

        想想我们编辑文档用的wps,文档里文字很多都是重复的,我们弗成能为每个涌现的汉字都创建独立的空间,这样代价太大,最好的方法就是同享其中雷同的部分,使得需要创建的对象降到最小,这个就是享元模式的核心,即运用同享技巧有效地支持大批细粒度的对象。

        享元对象能做到同享的关键是辨别内蕴状态(Internal State)和外蕴状态(External State)。内蕴状态是存储在享元对象外部并且不会随环境改变而改变。因此内蕴状态并可以同享。

        外蕴状态是随环境改变而改变的、弗成以同享的状态。享元对象的外蕴状态必须由客户端保存,并在享元对象被创建之后,在需要使用的时候再传入到享元对象外部。外蕴状态与内蕴状态是相互独立的。

        

    类图与样例

        

    元和对象

        抽象享元类(Flyweight

        它是全部详细享元类的超类。为这些类规定出需要实现的大众接口,那些需要外蕴状态(Exte的操纵可以通过方法的参数传入。抽象享元的接口使得享元变得可能,但是其实不强制子类实行同享,因此并非全部的享元对象都是可以同享的。

        详细享元类(ConcreteFlyweight)

        详细享元类实现了抽象享元类所规定的接口。如果有内蕴状态的话,必须担任为内蕴状态提供存储空间。享元对象的内蕴状态必须与对象所处的周围环境无关,从而使得享元对象可以在系统内同享。有时候详细享元类又称为单纯详细享元类,因为复合享元类是由单纯详细享元角色通过复合而成的。

        不能同享的详细享元类(UnsharableFlyweight)

        不能同享的享元类,又叫做复合享元类。一个复合享元对象是由多个单享元对象构成,这些构成的对象是可以同享的,但是复合享元类本身其实不能同享。

        享元工厂类(FlyweightFactoiy)

        享元工厂类担任创建和管理享元对象。当一个客户端对象请求一个享元对象的时候,享元工厂需要检查系统中是不是已经有一个符合要求的享元对象,如果已经有了,享元工厂角色就应当提供这个已有的享元对象;如果系统中没有恰当的享元对象的话,享元工厂角色就应当创建一个新的适合的享元对象。

        客户类(Client)

        客户类需要自行存储全部享元对象的外蕴状态。

        

        每日一道理
    风,那么轻柔,带动着小树、小草一起翩翩起舞,当一阵清风飘来,如同母亲的手轻轻抚摸自己的脸庞,我喜欢那种感觉,带有丝丝凉意,让人心旷神怡。享受生活,不一定要有山珍海味、菱罗绸缎为伴,大自然便是上帝所赐予人类最为珍贵的。
    // CplusplusFlyweight.cpp : Defines the entry point for the console application.
    //
    
    #include "stdafx.h"
    #include <iostream>
    #include <map>
    using namespace std;
    class Character  
    {
    public:
    	virtual ~Character(){};
    
    	virtual void SetSize(int, int) = 0;
    	virtual void Display() = 0;
    protected:
    	Character(){};
    	char m_chSymbol;
    	int m_nWeight;
    	int m_nHeight;
    };
    
    class CharacterA : public Character
    {
    public:
    	CharacterA();
    	virtual ~CharacterA();
    
    	void SetSize(int, int);
    	void Display();
    };
    
    CharacterA::CharacterA()
    {
    	this->m_chSymbol = 'A';
    	this->m_nWeight = 100;
    	this->m_nHeight = 200;
    }
    
    CharacterA::~CharacterA()
    {
    
    }
    void CharacterA::SetSize(int nWeight, int nHeight)
    {
    	this->m_nWeight = nWeight;
    	this->m_nHeight = nHeight;
    }
    void CharacterA::Display()
    {
    	cout << "CharacterA:" << m_chSymbol << "(" << m_nWeight << "," << m_nHeight << ")" << endl;
    }
    
    class CharacterB : public Character
    {
    public:
    	CharacterB();
    	virtual ~CharacterB();
    
    	void SetSize(int, int);
    	void Display();
    };
    
    CharacterB::CharacterB()
    {
    	this->m_chSymbol = 'B';
    	this->m_nWeight = 100;
    	this->m_nHeight = 200;
    }
    
    CharacterB::~CharacterB()
    {
    
    }
    
    void CharacterB::SetSize(int nWeight, int nHeight)
    {
    	this->m_nWeight = nWeight;
    	this->m_nHeight = nHeight;
    }
    
    void CharacterB::Display()
    {
    	cout << "CharacterB:" << m_chSymbol << "(" << m_nWeight << "," << m_nHeight << ")" << endl;
    }
    
    class CharacterFactory  
    {
    public:
    	CharacterFactory();
    	virtual ~CharacterFactory();
    
    	Character* GetCharacter(char);
    private:
    	std::map<char, Character*> m_mChar;
    };
    
    CharacterFactory::CharacterFactory()
    {
    	m_mChar.insert(make_pair<char, Character*>('A', new CharacterA));
    	m_mChar.insert(make_pair<char, Character*>('B', new CharacterB));
    }
    
    CharacterFactory::~CharacterFactory()
    {
    
    }
    
    Character* CharacterFactory::GetCharacter(char chIn)
    {
    	map<char, Character*>::iterator it = m_mChar.find(chIn);
    	if(it != m_mChar.end())
    	{
    		return (Character*)it->second;
    	}
    
    	return NULL;
    }
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	CharacterFactory* pFactory = new CharacterFactory;
    
    	//内蕴状态 存储在享元对象外部并且不会随环境改变而改变
    	Character* ch1 = pFactory->GetCharacter('A');
    	ch1->Display();
    
    	//外蕴状态 客户端保存
    	Character* ch2 = pFactory->GetCharacter('B');
    	ch2->SetSize(500, 800);
    	ch2->Display();
    	return 0;
    }

        

    要点

        1、面向对象很好的处理了抽象性的问题,但是作为一个运行在呆板中的程序实体,我们需要斟酌对象的代价问题。Flyweight设计模式重要处理面向对象的代价问题,一般不触及面向对象的抽象性问题。

        2Flyweight采用对象同享的做法来下降系统中对象的个数,从而下降细粒度对象给系统带来的内存压力。在详细实现方面,要注意对象状态的处理。

        3、享元模式的长处在于它大幅度地下降内存中对象的数量。但是,它做到这一点所付出的代价也是很高的:享元模式使得系统更加复杂。为了使对象可以同享,需要将一些状态外部化,这使得程序的逻辑复杂化。另外它将享元对象的状态外部化,而读取外部状态使得运行时间稍微变长。

        

    适用性

        当以下全部的条件都满足时,可以斟酌使用享元模式:

        1、一个系统有大批的对象。 

        2、这些对象耗费大批的内存。 

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

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

        5、软件系统不依赖于这些对象的身份,换言之,这些对象可以是弗成分辨的。

        满足以上的这些条件的系统可以使用享元对象。最后,使用享元模式需要维护一个记录了系统已有的全部享元的表,而这需要耗费资源。因此,应当在有足够多的享元实例可供同享时才值得使用享元模式。

        

    优缺点

        享元模式的长处在于它大幅度地下降内存中对象的数量。但是,它做到这一点所付出的代价也是很高的:

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

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

        

        LCL_data原创于CSDN.NET【http://blog.csdn.net/lcl_data/article/details/8974679

    文章结束给大家分享下程序员的一些笑话语录: IBM和波音777
      波音777是有史以来第一架完全在电脑虚拟现实中设计制造的飞机,所用的设备完全由IBM公司所提供。试飞前,波音公司的总裁非常热情的邀请IBM的技术主管去参加试飞,可那位主管却说道:“啊,非常荣幸,可惜那天是我妻子的生日,So..”..
      波音公司的总载一听就生气了:“胆小鬼,我还没告诉你试飞的日期呢!”

    --------------------------------- 原创文章 By
    元和对象
    ---------------------------------

  • 相关阅读:
    openssh的服务端配置文件
    SSH的端口转发
    ssh服务
    文件引入
    数据类型的转换
    作用域
    静态变量
    函数
    php嵌入html的解析过程
    PHP执行过程
  • 原文地址:https://www.cnblogs.com/jiangu66/p/3100664.html
Copyright © 2020-2023  润新知