Design Pattern -- Flyweight

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
// flyweight.cpp : Defines the entry point for the console application.
// author: chillyc
// email: chillycreator @t gmail.com

#include<iostream>
#include<map>
namespace pattern{

/// this is flyweight pattern
/// In text processing, there will be thousands of hundreds of characters.
/// If we construct too many this class instance, and
/// imaging this class will have many member variables, will the system be efficient?
/// So we just record the characters state, and not care about other part of character.
/// we shall save a lot of main memories, shall we?
/// If there are many characters, but they are only in differnt place, we can reuse characters.
/// So there are Fly_Manager to record the shared objects or states.
/// All objects should be derived from Metadata class.
/// Graphdata is no-shared metadata. And Character is shared metadata.
/// In main function, you will see the difference between two of them.

#ifndef STATE_H
#define STATE_H
class State{
private:
int font_num;
int style;

public:
void Set_Font_Num(int num){font_num = num;}
void Set_Style(int style){this->style = style;}
int Get_Font_Num(){return font_num;}
int Get_Style(){return style;}
State(){}
State(int num,int style){
font_num = num;
this->style = style;
}
State(const State& state){
this->font_num = state.font_num;
this->style = state.style;
}
State* operator = (const State& state){
this->font_num = state.font_num;
this->style = state.style;
return this;
}
};

#endif

#ifndef METADATA_H
#define METADATA_H
class Metadata{
public:
virtual void show()=0;
};
#endif

#ifndef character_H
#define character_H
// share the basic information
// here you should image character has a huge infomation,
// and state is only a small part of this class
class character: public Metadata{
private:
State state;
public:
// set state to default state
character():Metadata(),state(1,1){}
~character(){}
void Set_State(State& state);
virtual void show();

};
void character::Set_State(pattern::State& state){
this->state = state;
}

void character::show(){
std::cout << "write a character font is "<< state.Get_Font_Num()<< " style is "
<< state.Get_Style()<<std::endl;
}
#endif

#ifndef GRAPHDATA_H
#define GRAPHDATA_H
// not share
class Graphdata: public Metadata{
private:
State state;
public:
Graphdata(State & state):Metadata(),state(state){}
// font num is not used
Graphdata(int style):Metadata(),state(-1,style){}
~Graphdata(){};
virtual void show();
};

#endif
void Graphdata::show(){
// only use its own state
std::cout<< "print a graph! style is "<<state.Get_Style()<<std::endl;
}

#ifndef FLYMANAGER_H
#define FLYMANAGER_H
class Fly_Manager{
public:
// suggest you should make it as private or protected
std::map<int,State> characters;
Fly_Manager(){}
void Set_I(int i, State& state);
State& Get_I(int i);
~Fly_Manager(){}

};
#endif
void Fly_Manager::Set_I(int i, State& state){
characters[i] = state;
}
State& Fly_Manager::Get_I(int i){
return characters[i];
}

}
int main()
{
pattern::Fly_Manager fm;
pattern::character c;
pattern::State s1(1,2);
pattern::State s2(2,3);
pattern::State s3(3,4);
fm.Set_I(0,s1);
fm.Set_I(1,s2);
fm.Set_I(2,s3);
pattern::Graphdata gd1(2);
pattern::Graphdata gd2(9);
for(int i = 0; i < 3; i++){
c.Set_State(fm.Get_I(i));
c.show();
}
gd1.show();
gd2.show();
return 0;
}