Skip to content

Commit 71a03f4

Browse files
committed
add flyweight
1 parent 52d9d20 commit 71a03f4

File tree

7 files changed

+283
-2
lines changed

7 files changed

+283
-2
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,9 @@
2929

3030
[装饰模式 Decorator](doc/11-装饰.md)
3131

32-
外观模式 Facade
32+
[外观模式 Facade](doc/12-外观.md)
3333

34-
享元模式 Flyweight
34+
[享元模式 Flyweight](doc/13-享元.md)
3535

3636
代理模式 Proxy
3737

code/12_flyweight/12_flyweight.sln

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio Version 16
4+
VisualStudioVersion = 16.0.29215.179
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "12_flyweight", "12_flyweight.vcxproj", "{5A9F1042-FC13-4D22-98F4-1CD74024C6FF}"
7+
EndProject
8+
Global
9+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
10+
Debug|x64 = Debug|x64
11+
Debug|x86 = Debug|x86
12+
Release|x64 = Release|x64
13+
Release|x86 = Release|x86
14+
EndGlobalSection
15+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
16+
{5A9F1042-FC13-4D22-98F4-1CD74024C6FF}.Debug|x64.ActiveCfg = Debug|x64
17+
{5A9F1042-FC13-4D22-98F4-1CD74024C6FF}.Debug|x64.Build.0 = Debug|x64
18+
{5A9F1042-FC13-4D22-98F4-1CD74024C6FF}.Debug|x86.ActiveCfg = Debug|Win32
19+
{5A9F1042-FC13-4D22-98F4-1CD74024C6FF}.Debug|x86.Build.0 = Debug|Win32
20+
{5A9F1042-FC13-4D22-98F4-1CD74024C6FF}.Release|x64.ActiveCfg = Release|x64
21+
{5A9F1042-FC13-4D22-98F4-1CD74024C6FF}.Release|x64.Build.0 = Release|x64
22+
{5A9F1042-FC13-4D22-98F4-1CD74024C6FF}.Release|x86.ActiveCfg = Release|Win32
23+
{5A9F1042-FC13-4D22-98F4-1CD74024C6FF}.Release|x86.Build.0 = Release|Win32
24+
EndGlobalSection
25+
GlobalSection(SolutionProperties) = preSolution
26+
HideSolutionNode = FALSE
27+
EndGlobalSection
28+
GlobalSection(ExtensibilityGlobals) = postSolution
29+
SolutionGuid = {E3FB86BB-06AB-4C5E-B3B5-DAEEA821AD1A}
30+
EndGlobalSection
31+
EndGlobal

code/12_flyweight/chess.h

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
#pragma once
2+
#include <iostream>
3+
#include <map>
4+
using namespace std;
5+
6+
enum Color {
7+
WHITE, BLACK
8+
};
9+
10+
struct Point {
11+
int x, y;
12+
};
13+
14+
class Chess {
15+
public:
16+
void draw() {
17+
cout << "Chess " << (m_color==WHITE?"white":"black") << " at position:("<< m_pos.x<<","<< m_pos.y<<")" << endl;
18+
}
19+
Color getColor() {
20+
return m_color;
21+
}
22+
Point getPoint() {
23+
return m_pos;
24+
}
25+
void setPoint(int x, int y) {
26+
m_pos.x = x;
27+
m_pos.y = y;
28+
}
29+
protected:
30+
Color m_color;
31+
private:
32+
Point m_pos;
33+
};
34+
35+
class WhiteChess :public Chess {
36+
public:
37+
WhiteChess() {
38+
m_color = WHITE;
39+
}
40+
};
41+
42+
class BlackChess :public Chess {
43+
public:
44+
BlackChess() {
45+
m_color = BLACK;
46+
}
47+
};
48+
49+
class ChessFactory {
50+
public:
51+
Chess* getChess(Color color) {
52+
map<Color, Chess*>::iterator l_it = m_chesses.find(color);
53+
Chess* ret = nullptr;
54+
if (l_it == m_chesses.end()) {
55+
switch (color)
56+
{
57+
case WHITE:
58+
ret = new WhiteChess;
59+
break;
60+
default:
61+
ret = new BlackChess;
62+
break;
63+
}
64+
m_chesses[color] = ret;
65+
return ret;
66+
}
67+
return (*l_it).second;
68+
}
69+
private:
70+
map<Color, Chess*> m_chesses;
71+
};

code/12_flyweight/client.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#include "chess.h"
2+
3+
int main() {
4+
5+
ChessFactory factory;
6+
7+
Chess* white1 = factory.getChess(Color::WHITE);
8+
white1->setPoint(0, 0);
9+
white1->draw();
10+
11+
Chess* black1 = factory.getChess(Color::BLACK);
12+
black1->setPoint(1, 1);
13+
black1->draw();
14+
15+
16+
Chess* white2 = factory.getChess(Color::WHITE);
17+
white2->setPoint(2, 6);
18+
white2->draw();
19+
20+
Chess* black2 = factory.getChess(Color::BLACK);
21+
black2->setPoint(3, 4);
22+
black2->draw();
23+
24+
return 0;
25+
}

doc/13-享元.md

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
# 享元
2+
3+
运用共享技术来有效地支持大量细粒度对象的复用。它通过共享已经存在的对象来大幅度减少需要创建的对象数量、避免大量相似类的开销,从而提高系统资源的利用率。
4+
5+
## UML
6+
7+
享元模式常常结合工厂模式一起使用,其结构包含抽象享元类、具体享元类、非共享具体享元类和享元工厂类:
8+
* Flyweight(抽象享元类): 是一个抽象类,声明了具体享元类公共的方法,这些方法可以向外部提供享元对象的内部状态数据,也可以通过这些方法设置外部状态
9+
* ConcreteFlyweight(具体享元类): 具体实现抽象享元类声明的方法,具体享元类中为内部状态提供存储空间
10+
* UnsharedConcreteFlyweight(非共享具体享元类): 并不是所有抽象享元类的子类都需要被共享,可以将这些类设计为非共享具体享元类
11+
* FlyweightFactory(享元工厂类): 于创建并管理享元对象,针对抽象享元类编程,将各种具体享元类对象存储在一个享元池中,享元池一般设计为一个存储键值对的集合(或者其他类型的集合),可结合工厂模式设计。客户需要某个享元对象时,如果享元池中已有该对象实例,则返回该实例,否则创建一个新的实例,给客户返回新的实例,并将新实例保存在享元池中
12+
13+
![figure12_flyweight](img/figure12_flyweight.png)
14+
15+
## 优缺点
16+
17+
* 优点
18+
* 享元模式通过享元池存储已经创建好的享元对象,实现相同或相似的细粒度对象的复用,大大减少了系统中的对象数量,节约了内存空间,提升了系统性能
19+
* 享元模式通过内部状态和外部状态的区分,外部状态相互独立,客户端可以根据需求任意使用
20+
21+
* 缺点
22+
* 享元模式需要增加逻辑来取分出内部状态和外部状态,增加了编程的复杂度
23+
24+
## 使用场景
25+
26+
* 当一个系统中有大量重复使用的相同或相似对象时,使用享元模式可以节约系统资源
27+
* 对象的大部分状态都可以外部化,可以将这些状态传入对象中
28+
29+
## 用例
30+
电子围棋和传统围棋一样有黑白子两种, 棋盘上的棋子是通过在屏幕上画出来的, 对于电子围棋的话,就不需要创建非常多的黑白棋子,只需要创建一共两个棋子:黑子和白子各一个,通过改变它们的位置再更新到屏幕上
31+
32+
[code](../code/12_flyweight)
33+
34+
```c++
35+
#pragma once
36+
#include <iostream>
37+
#include <map>
38+
using namespace std;
39+
40+
enum Color {
41+
WHITE, BLACK
42+
};
43+
44+
struct Point {
45+
int x, y;
46+
};
47+
48+
class Chess {
49+
public:
50+
void draw() {
51+
cout << "Chess " << (m_color==WHITE?"white":"black") << " at position:("<< m_pos.x<<","<< m_pos.y<<")" << endl;
52+
}
53+
Color getColor() {
54+
return m_color;
55+
}
56+
Point getPoint() {
57+
return m_pos;
58+
}
59+
void setPoint(int x, int y) {
60+
m_pos.x = x;
61+
m_pos.y = y;
62+
}
63+
protected:
64+
Color m_color;
65+
private:
66+
Point m_pos;
67+
};
68+
69+
class WhiteChess :public Chess {
70+
public:
71+
WhiteChess() {
72+
m_color = WHITE;
73+
}
74+
};
75+
76+
class BlackChess :public Chess {
77+
public:
78+
BlackChess() {
79+
m_color = BLACK;
80+
}
81+
};
82+
83+
class ChessFactory {
84+
public:
85+
Chess* getChess(Color color) {
86+
map<Color, Chess*>::iterator l_it = m_chesses.find(color);
87+
Chess* ret = nullptr;
88+
if (l_it == m_chesses.end()) {
89+
switch (color)
90+
{
91+
case WHITE:
92+
ret = new WhiteChess;
93+
break;
94+
default:
95+
ret = new BlackChess;
96+
break;
97+
}
98+
m_chesses[color] = ret;
99+
return ret;
100+
}
101+
return (*l_it).second;
102+
}
103+
private:
104+
map<Color, Chess*> m_chesses;
105+
};
106+
```
107+
108+
```c++
109+
#include "chess.h"
110+
111+
int main() {
112+
113+
ChessFactory factory;
114+
115+
Chess* white1 = factory.getChess(Color::WHITE);
116+
white1->setPoint(0, 0);
117+
white1->draw();
118+
119+
Chess* black1 = factory.getChess(Color::BLACK);
120+
black1->setPoint(1, 1);
121+
black1->draw();
122+
123+
124+
Chess* white2 = factory.getChess(Color::WHITE);
125+
white2->setPoint(2, 6);
126+
white2->draw();
127+
128+
Chess* black2 = factory.getChess(Color::BLACK);
129+
black2->setPoint(3, 4);
130+
black2->draw();
131+
132+
return 0;
133+
}
134+
```

doc/img/figure12_flyweight.png

13.9 KB
Loading

doc/uml/12_flyweight.pu

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
@startuml "figure12_flyweight"
2+
caption figure12: Flyweight
3+
4+
class Flyweight{}
5+
class ConcreteFlyweight{
6+
- key:string
7+
}
8+
class UnsharedConcreteFlyweight{}
9+
10+
Flyweight <|-- ConcreteFlyweight
11+
Flyweight <|-- UnsharedConcreteFlyweight
12+
13+
14+
class FlyweightFactory{
15+
- flyweights: Map<string,FlyWeight>
16+
+ getFlyWeight(key:string): FlyWeight;
17+
}
18+
19+
FlyweightFactory o-- Flyweight
20+
@enduml

0 commit comments

Comments
 (0)