①The essence of Flyweight mode : separation and sharing. The key to Flyweight mode is to separate change and invariance. The unchanged part is regarded as the internal state of the Flyweight object , and the changed part is regarded as the external state , which is maintained by the outside. In this way, Flyweight objects can be shared, thereby reducing the number of objects. quantity, and save a lot of memory space.
② Changes and changes of Flyweight mode: Why should an interface be reserved in one place? A common reason is that there are changes here, and the existing implementation may need to be extended or changed in the future, and the reserved interface is used as a "pluggable" interface. guarantee"
③ Flyweight object: there are shared (ConcreteFlyweight) and unshared (UnsharedConcreteFlyweight) points. Unshared generally occurs when combined with the composition mode . Usually, the shared object is a leaf object. Generally, the unshared part is composed of the shared part. Since all fine-grained leaf objects have been cached, there is nothing to cache the combined object. significance. (For example , the "view" and "modify" of a security entity in permission management can be shared . If the "view" and "modify" are combined into the "operation" permission , the " operation" permission does not need to be cached (shared). , because it is already cached at a fine-grained level ). (see example later)
【Programming Experiment】Go Software Design
①Internal state: There are so many pieces in each Go, which can be set as Flyweight objects, with the following attributes: color, size, and shape.
②External state: the position of the piece on the chessboard. This is not shareable.
//declaration file
//Structural pattern: flyweight pattern //Scenario: Go software design. //Internal state - There are many Go pieces, but they are only divided into two categories: white and black. // Has properties such as color, size, shape, etc., and is a sharable object. //External state - the position of the piece on the board. #include <iostream> #include <string> #include <map> using namespace std; //************************************Hyweight class ********* **************** //Non-flyweight object: UnsharedConcreteFlyweight (external state) class CPos{ private: int X; int Y; public: CPos(int x, int y); void SetX(int x); int GetX(); void SetY(int y); int GetY (); }; // Flyweight abstract class class CWeight{ protected: string strColor; public: virtual ~CWeight(); void SetColor(string color); string GetColor(); //Display the position of the pieces on the chessboard //You can pass the external state into the flyweight object through this interface virtual void Disp(CPos& pos) = 0; }; //Flyweight object: ConcreteFlyweight (internal state) class CFly : public CWeight{ public: CFly(string color); ~CFly(); void Disp(CPos& pos); }; //************************************Hygware Factory Class******** ******************** class CChessFac{ private: static map<string, CWeight*> mpChess; public: static CWeight* GetChess(string color); static void RemoveAll(); };
//implementation file
//************************************Hyweight class ********* **************** //Non-flyweight object: UnsharedConcreteFlyweight (external state) CPos::CPos(int x, int y){X = x; Y = y;} void CPos::SetX(int x){ X = x;} int CPos::GetX(){return X;} void CPos::SetY(int y){Y = y;} int CPos::GetY(){return Y;} // Flyweight abstract class CWeight::~CWeight(){cout << "~CWeight" << endl;} void CWeight::SetColor(string color){strColor = color;} string CWeight::GetColor(){return strColor;} //Flyweight object: ConcreteFlyweight (internal state) CFly::CFly(string color){SetColor(color);} CFly::~CFly(){cout << "~CFly" << endl; } void CFly::Disp(CPos& pos) { cout << "********************************************" << endl; cout << "Chess's Color : " << strColor << endl; cout << "Chess's Pos : (" << pos.GetX() << ", " << pos.GetY() << ")" << endl; cout << "********************************************" << endl << endl; } //************************************Hygware Factory Class******** ******************** map<string, CWeight*> CChessFac::mpChess; CWeight* CChessFac::GetChess(string color) { CWeight* pChess = mpChess[color]; if(pChess == NULL){ pChess = new CFly(color); mpChess[color] = pChess; } return pChess; } void CChessFac::RemoveAll() { cout << "Before deleting... size = " << mpChess.size() << endl; for(map<string, CWeight*>::iterator it = mpChess.begin(); it != mpChess.end(); ){ cout << it->first << " : " << it->second << endl; CWeight* pWeight = it->second; delete pWeight; it = mpChess.erase(it); } cout << "After deleted... size = " << mpChess.size() << endl; }
//test client
void main() { CWeight* pChess1 = CChessFac::GetChess("Black"); CWeight* pChess2 = CChessFac::GetChess("White"); CWeight* pChess3 = CChessFac::GetChess("Black"); cout << "pChess1 : " << pChess1 << endl; cout << "pChess2 : " << pChess2 << endl; cout << "pChess3 : " << pChess3 << endl; pChess1->Disp(CPos(10,10)); pChess2->Disp(CPos(20,20)); pChess3->Disp(CPos(30,30)); CChessFac::RemoveAll(); }