設計模式之享元模式

2018-09-21  10:07:30ios

享元模式

  享元模式(Flyweight),運用共享技術有效的支持大量細粒度的對象。編程

享元模式UML類圖

·  數據結構

FlyWeightFactory:用於建立並管理享元對象,它針對抽象享元類編程,將各類類型的具體享元對象存儲在一個享元池中,享元池通常設計爲一個存儲「鍵值對」的集合(也能夠是其餘類型的集合),能夠結合工廠模式進行設計;當用戶請求一個具體享元對象時,享元工廠提供一個存儲在享元池中已建立的實例或者建立一個新的實例(若是不存在的話),返回新建立的實例並將其存儲在享元池中。它的做用主要是爲了建立並管理共享元對象,確保合理的共享Flyweight。ide

Flyweight:全部具體享元類的公共基類,經過這個基類,Flyweight能夠接收並做用於外部狀態。性能

SharedConcreteFlyweight(ConcreteFlyweight):實現了抽象享元類,其實例稱爲享元對象,在具體享元類裏爲內部狀態提供了存儲空間,一般能夠結合單例模式來設計具體享元類,爲每一個享元類提供惟一的享元對象。大部分時候須要使用共享元對象來下降內存的損耗,可是並非全部狀況下都須要共享元,這就是UnSharedConcreteFlyweight類存在的必要性。spa

UnSharedConcreteFlyweight:這個類是指那些不須要共享的對象,雖然經過共享模式的設計(Flyweight),使得對象的共享成爲可能,可是它並不會強制共享。由於在客戶端使用的時候必然會有不須要共享的對象。它的存在就是爲了解決那些不須要共享對象的問題。設計

  共享元模式是和工廠模式是有些類似的,區別在於一方面共享元模式提供了對象的動態加入功能,另外一方面共享元模式下客戶端代碼不是隻能使用有共享元工廠建立的產品,它能夠直接使用UnSharedConcreteFlyweight的對象。另外享元模式的根本目的是爲了共享對象,減小代碼實例的個數,同時也提升了代碼的複用性,它在使用的時候,必然是對象之間具備某種類似性才能夠,而表現出的不一樣之處則在於外部狀態的不一樣。3d

內部狀態與外部狀態

  在享元對象內部而且不會隨環境的改變而改變的共享部分,能夠稱爲是享元對象的內部狀態,而隨環境改變而改變的、不能夠共享的狀態就是外部狀態了,固然享元是能夠沒有內部狀態的,而外部狀態最好由客戶代碼或者第三方類託管。事實上,享元模式能夠避免大量很是類似類的開銷。在程序設計找那個,有時須要生成大量細粒度的類實例來表示數據。若是發現這些實例除了幾個參數外基本上都是相同的,有時就能大幅度的減小須要實例化的類的數量。若是能把那些參數移到類實例的外部,在方法調用時將它們(外部狀態)傳遞進來,就能夠經過共享大幅度的減小單個實例的數目。code

享元模式的優缺點對象

優勢:

  1.經過共享對象節約了內存資源下降了性能消耗(有些狀況下,對象的數量太多,會致使運行時的資源與性能損耗)

  2.享元模式的內部狀態穩定不變,外部狀態則隨環境而改變且不會影響內部狀態,而外部狀態的不一樣又是的享元對象得出不一樣的運算的結果,這使得共享對象成爲了一種可能

缺點:

  1.享元模式須要維護一個記錄了系統已有的全部享元的列表,這自己也須要消耗資源,在每一次使用享元使都須要進行一次查找,這下降了程序的運行效率。

  2.享元模式使得系統更加的複雜,由於你須要抽離出享元的內部狀態和外部狀態,享元在不一樣環境下的外部狀態都不相同,這使得程序的邏輯複雜度提高。

適用場景:

  1.在對象(相同或類似的對象)足夠多的時候,而這些對象形成了很大的存儲開銷時應該考慮使用享元模式,還有就是對象的大多數狀態能夠抽離爲外部狀態,若是刪除對象的外部狀態,那麼能夠用相對較小的共享對象取代不少組對象,此時也能夠考慮使用共享模式。

  2.享元必須是被大量使用的纔有使用享元模式的價值,由於,在使用享元模式的時候須要維護一個全部已經存在的享元的key-value數據結構,這自己也是須要消耗資源的。

代碼示例

  問題模型:圍棋系統,在一個圍棋系統中,有黑子、白子、還有棋盤、裝棋子棋盒。其中黑子181個,白子180個,總共361個棋子,在下棋的過程當中,每一個棋子都會有本身的一個座標。棋盤總共有384格,若是你爲每一個實例化一個棋子對象,那麼將由384個棋子對象。這裏咱們可使用享元模式。接下來分析內部和外部狀態。對棋子、棋盤、棋盒,它們都有固定的顏色,這個是不會改變的,因此顏色是內部狀態。標準雙人模式下,棋盒只有兩個,棋盤一個,因此它們沒有共享的意義(可是它們相對於界面來講,依然有個顯示座標的問題,因此外部變量對他們依然成立)。對棋子來講,每一個對象的座標就是外部模式,根據座標的不一樣,棋子能夠顯示在棋盤上不一樣的位置。

1.抽象享元基類(Flyweight)

#ifndef FLYWEIGHT_H_
#define FLYWEIGHT_H_

#include <iostream>
#include <string>

class Flyweight
{
public:
    virtual void display(const int iX,const int iY) = 0;
    Flyweight() = default;
    virtual ~Flyweight() = default;
protected:
    std::string m_strColor;
};
#endif
Flyweight

2.共享類(SharedFlyweight)

#ifndef SHAREDFLYWEIGHTWHITE_H_
#define SHAREDFLYWEIGHTWHITE_H_
#include "Flyweight.h"

class SharedConcreteFlyweightWhite : public Flyweight
{
public:
    void display(const int iX,const int iY) override;
    SharedConcreteFlyweightWhite()
    {
    m_strColor = "White";
    }
    ~SharedConcreteFlyweightWhite() = default;
};
#endif

#include "SharedFlyweightWhite.h"

void SharedConcreteFlyweightWhite::display(const int iX,const int iY)
{
    std::cout << " I am a " << m_strColor << "chess pieces,my coordinate is (" << iX << "," << iY << ")." << std::endl;
}

#ifndef SHAREDFLYWEIGHTBLACK_H_
#define SHAREDFLYWEIGHTBLACK_H_

#include "Flyweight.h"

class SharedConcreteFlyweightBlack : public Flyweight
{
public:
   void display(const int iX,const int iY) override;
   SharedConcreteFlyweightBlack()
   {
    m_strColor = "Black";
   }
   ~SharedConcreteFlyweightBlack() = default;
};

#endif

#include "SharedFlyweightBlack.h"

void SharedConcreteFlyweightBlack::display(const int iX,const int iY)
{
    std::cout << "I am a black Chess,my coordinate is (" << iX << "," << iY << ")" << std::endl;
}
SharedFlyweight

3.非共享的享元類(UnsharedFlyweight)

#ifndef UNSHAREDCONCRETEFLYWEIGHTCHESSBOX_H_
#define UNSHAREDCONCRETEFLYWEIGHTCHESSBOX_H_

#include "Flyweight.h"

class UnsharedConcreteFlyweightChessbox : public Flyweight
{
public:
    void display(const int iX,const int iY) override;
    UnsharedConcreteFlyweightChessbox()
    {
    m_strColor = "Yellow";
    }
    ~UnsharedConcreteFlyweightChessbox() = default;
};
#endif 

#include "UnsharedConcreteFlyweightChessBox.h"

void UnsharedConcreteFlyweightChessbox::display(const int iX,const int iY)
{
    std::cout << "I am a " << m_strColor << " chessbox,my coordinate is (" << iX << "," << iY << ")" <<std::endl;
}
UnsharedFlyweight

4.Flyweight(享元模式的核心部件)

#ifndef FLYWEIGHTFACTORY_H_
#define FLYWEIGHTFACTORY_H_

#include "Flyweight.h"
#include "SharedFlyweightWhite.h"
#include "SharedFlyweightBlack.h"
const std::string BLACKCHESS = "Black";
const std::string WHITECHESS = "White";
#include <map>
class FlyweightFactory
{
private:
    std::map<std::string,Flyweight*> m_mapFlyweight;
public:
    Flyweight* getFlyweight(const std::string strKey);
    int getFlyweightCount()
    {
    return m_mapFlyweight.size();
    }
};
#endif

#include "FlyweightFactory.h"

// strKey is defined class name or surname of class 
Flyweight* FlyweightFactory::getFlyweight(const std::string strKey)
{
    //if find return FlyWeight object whose key is equal,otherwise new object and insert into map
    if(m_mapFlyweight.end() != m_mapFlyweight.find(strKey))
    return m_mapFlyweight[strKey];
    if(strKey == BLACKCHESS)
    {
        auto pointer = new SharedConcreteFlyweightBlack;
    m_mapFlyweight[strKey] = pointer;
        return pointer;
    }
    else if(strKey == WHITECHESS)
    {
        auto pointer  = new SharedConcreteFlyweightWhite;
        m_mapFlyweight[strKey] = pointer;
        return pointer;
    }
    else
    {
    std::cout << "The key is Error!" << std::endl;
      return nullptr;
    }
}
Flyweight

5.Client

#include "FlyweightFactory.h"
#include "UnsharedConcreteFlyweightCheckerboard.h"
#include "UnsharedConcreteFlyweightChessBox.h"

using namespace std;

int main(int argc,char *argv[])
{
    FlyweightFactory objFactory;
    auto objBlack = objFactory.getFlyweight(BLACKCHESS);
    if(nullptr != objBlack)
    objBlack->display(3,5);
    auto objBlack1 = objFactory.getFlyweight(BLACKCHESS);
    if(nullptr != objBlack1)
    objBlack1->display(1,4);
    std::cout << "count "<< objFactory.getFlyweightCount() << std::endl;
   
    auto objWhite = objFactory.getFlyweight(WHITECHESS);
    if(nullptr != objWhite)
    objWhite->display(9,9);
    std::cout << "count:" << objFactory.getFlyweightCount() << std::endl;
    auto objWhite1 = objFactory.getFlyweight(WHITECHESS);
    if(nullptr != objWhite1)
    objWhite1->display(8,8);
    std::cout << "count: "<< objFactory.getFlyweightCount() << std::endl;
    UnsharedConcreteFlyweightChessbox  unshChessbox;
    unshChessbox.display(1,2);
    std::cout <<"count:" << objFactory.getFlyweightCount() << std::endl;
    return(1);
}
Client
相關文章
相關標籤/搜索