zoukankan      html  css  js  c++  java
  • 元对象我所理解的设计模式(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
    元和对象
    ---------------------------------

  • 相关阅读:
    MFC tab页面中获到其它页面的数据
    sqlite数据库中"Select * From XXX能查到数据,但是Select DISTINCT group From xxx Order By group却查不出来
    关闭程序出现崩溃(exe 已触发了一个断点及未加载ucrtbased.pdb)
    springboot 通用Mapper使用
    springBoot 发布war包
    springCloud Zuul网关
    springboot hystrix turbine 聚合监控
    springBoot Feign Hystrix Dashboard
    springBoot Ribbon Hystrix Dashboard
    springBoot Feign Hystrix
  • 原文地址:https://www.cnblogs.com/jiangu66/p/3100664.html
Copyright © 2011-2022 走看看