1. Trang chủ
  2. » Luận Văn - Báo Cáo

seminar report flyweight design pattern

14 0 0
Tài liệu được quét OCR, nội dung có thể không chính xác
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Tiêu đề Flyweight Design Pattern
Tác giả Nguyễn Hữu Quốc Thắng, Nguyễn Chớnh Thụng, Pham Trung Nghĩa, Nguyễn Đức Thọ
Trường học University Of Science
Chuyên ngành Seminar
Thể loại Seminar Report
Năm xuất bản 2023
Thành phố Ho Chi Minh City
Định dạng
Số trang 14
Dung lượng 1,06 MB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

The Flyweight pattern is a structural pattern, which uses “sharing to support large numbers of fine-grained objects efficiently.” In simpler terms, it allows sharing common parts of each

Trang 1

VIETNAM NATIONAL UNIVERSITY HO CHI MINH CITY

UNIVERSITY OF SCIENCE

C KHOA

DHQG-HCM

oO

SEMINAR REPORT

FLYWEIGHT DESIGN PATTERN

Members of Group 05: Nguyễn Hữu Quốc Thắng

Nguyễn Chính Thông Pham Trung Nghĩa Nguyễn Đức Thọ

Ho Chi Minh City, 16/12/2023

Trang 2

Contents

Definition

Example

Real World Problems

Pros/Cons of State

11

12

Trang 3

1

1

8

9

10

Imagine you’re building a game, where the purpose is to answer the age old question: “Why

does the chicken cross the road?”

Yes, we’re building a crossing game Like Crossy Road [1] Or Frogger [2]

When we start a new game, a new World should be created Where there are trees, rocks, and, of course, obstacles, like water blocks, trains, and the like

Let’s start with creating a game world The world should have many lanes, like normal land, train tracks, river blocks, and roads We call these “blocks” These blocks have some properties, such as its sprite, its position, its type, what kind of obstacle it contains, and so on

On code, a block would look like this [3]:

class Block

{

protected:

sf:

sf:

sf:

sf:

:Sprite m_sprite;

:Texture m_texture;

:Vector2f m_position;

:Vector2f m_scale = {1, 1};

ObstacleType m_obstacleType;

Obstacle *obstacle;

bool m_isContainObs = 0;

BlockType m_type;

bool m đirecion; //1-left, 0-right

And a single lane would look like this [4]:

class Lane

{

private:

sf::Vector2f m_startingPosition;

vector<Block *> blocks;

float v = 0;

public:

Lane();

~Lane();

Trang 4

void addBlock(Block *block);

void draw(sf::RenderWindow &window);

Block* getBlock(int index) ;

void Update(const sf::Time& 1 time);

bool isAbleToStepOn(int index) ;

int getV();

NONE =0

DUCKWEED

RIVERLOG

TREE

CAR

After compiling the code and running it, suddenly, the computer’s fans begin to speed up

to maximum When you open Task Manager, you noticed the GPU usage spiked up to 100%,

BlockType

FINISH = -1

LAND

WATER

ROAD

Block

#m_spmite: sh:Sprite

# m_texture: sf: Texture

# m_position: sf::Vector2f

# m_scale: sf: Vector2t

# m_obstacleType: Obstacle Type

# obstacle: Obstacle

# m_type: BlockType

#m_isContainObs = 0: bool

} ——<> - blocks: std::vector<Block *>

- velocity = 0: float

+ addBlock(block: Block"): void

World

+ generateLane(); void + generateLane(type: BlockType): void

Figure 1: Diagram of the naive solution

and you have no idea why

void World::draw(sf-:RenderWindow &window) {

for (int | = lanes.size() - 1; 1 >= 0; i-){ lanes{i}->draw(window),

m_player->draw(window):

}

Trang 5

File Options View Processes Performance App history Startup Users Details Services

38% 0% 0% Y 99%

Memory Disk} Network GPU engine

ñ#T Client Ser/er Runtime Process 0.2% 14MB OMB/s O Mbps 0.1% GPUO-:

3 Service Host: Diagnostic Service 0.9 MB OMB/s O Mbps

=5 Service Host: Group Policy Client 1.2MB OMB/s O Mbps Adobe IPC Broker (32 bit) 06MB OMB/s O Mbps i] Antimalware Core Service 14 MB O MB/s 0 Mbps

Figure 2: GPU maxed out on running the C$202 Project

The problem is the design of the lanes itself Because the data of each block is stored on a single object, it begins to fill wp the available memory This becomes especially alarming when

we develop a level progression system, where the number of levels begin to increase, and so

is the lane count for each level And that’s not accounting for each of the obstacles that are present on each lane, such as the cars on the road, the small logs on the rivers, the trains,

On many limited-spec machines, it would crash immediately, while on stronger machines,

it would hamper the system’s performance massively

The Flyweight pattern is a structural pattern, which uses “sharing to support large numbers

of fine-grained objects efficiently.”

In simpler terms, it allows sharing common parts of each objects instead of keeping all the data in one single object, greatly reducing RAM usage

The Flyweight pattern is merely an optimization Before applying it, make sure your program does have the RAM consumption problem related to having a massive number of similar objects in memory at the same time Make sure that this problem can’t be solved in any other meaningful way

Let have a look at the structure of Flyweight pattern:

Trang 6

FlyweightFactory Client

- cache: Flyweight[] ©

- flyweight

+ operation()

factory.getFlyweight(repeatingState)

- repeatingState

Figure 3: Structure of FlyWeight Pattern

The Flyweight class contains the portion of the original object’s state that can be shared between multiple objects The same flyweight object can be used in many different contexts The state stored inside a flyweight is called intrinsic The state passed to the flyweight’s

methods is called extrinsic

The Context class contains the extrinsic state, unique across all original objects When a

context is paired with one of the flyweight objects, it represents the full state of the original

object

Usually, the behavior of the original object remains in the flyweight class In this case, whoever calls a flyweight’s method must also pass appropriate bits of the extrinsic state into the method’s parameters On the other hand, the behavior can be moved to the context class, which would use the linked flyweight merely as a data object

The Client calculates or stores the extrinsic state of flyweights From the client’s per- spective, a flyweight is a template object which can be configured at runtime by passing some contextual data into parameters of its methods

The Flyweight Factory manages a pool of existing flyweights With the factory, clients don’t create flyweights directly Instead, they call the factory, passing it bits of the intrinsic state of the desired flyweight The factory looks over previously created flyweights and either returns an existing one that matches search criteria or creates a new one if nothing is found

2.2 Implementation

1 Divide fields of a class that will become a flyweight into two parts:

* the intrinsic state: the fields that contain unchanging data duplicated across many objects

* the extrinsic state: the fields that contain contextual data unique to each object

2 Leave the fields that represent the intrinsic state in the class, but make sure they’re immutable They should take their initial values only inside the constructor

3 Go over methods that use fields of the extrinsic state For each field used in the method,

introduce a new parameter and use it instead of the field

Trang 7

4

6

9

4, Optionally, create a factory class to manage the pool of flyweights It should check for

an existing flyweight before creating a new one Once the factory is in place, clients must only request flyweights through it They should describe the desired flyweight by passing its intrinsic state to the factory

5 The client must store or calculate values of the extrinsic state (context) to be able to call

methods of flyweight objects For the sake of convenience, the extrinsic state along with the flyweight-referencing field may be moved to a separate context class

3 Example

To better understand how to implement the Flyweight design pattern, let’s look at a sim- ple example about the management of information about cars and the sharing of common information about them to reduce memory usage

This example illustrates the structure of the Flyweight design pattern [5] It focuses on answering these questions:

« What classes does it consist of?

« What roles do these classes play?

« In what way the elements of the pattern are related?

[**

* Flyweight Design Pattern

*

* Intent: Lets you fit more objects into the available amount of RAM

* by sharing common parts of state between multiple objects,

* instead of keeping all of the data in each object

*/

struct SharedState

{

std::string brand_;

std::string model_;

std::string color_;

SharedState(const std::string &brand, const std::string &model,

const std::string &color)

: brand_(brand), model_(model), color_(color)

friend std::ostream koperator<<(std::ostream &%os, const SharedState &ss)

{

return os << "[ " << ss.brand_ << " , " << ss.model_

6

Trang 8

};

<<", " << s8.color_ << " J";

struct UniqueState

{

std::string owner_;

std::string plates_;

UniqueState(const std::string &owner, const std::string &plates)

owner_(owner), plates_(plates) {

+

friend std::ostream #operator<<(std::ostream &os, const UniqueState &us)

{

return os << "[ " << us.owner_ << ", " << us.plates_ << " |";

+

I;

Next, we implement the Fly Weight Class:

[**

* The Flyweight stores a common portion of the state (also called intrinsic

* state) that belongs to multiple real business entities The Flyweight accepts

* the rest of the state (extrinsic state, unique for each entity) via its

* method parameters

*/

class Flyweight

{

private:

SharedState *shared_state_;

public:

Flyweight (const SharedState *shared_state) : shared_state_(new

{

}

Flyweight(const Flyweight &other) : shared_state_(new

SharedState(*other.shared_state_))

{

Trang 9

}

~Flyweight()

{

delete shared_state_;

}

SharedState *shared_state() const

{

return shared_state_;

}

void Operation(const UniqueState &unique_state) const

{

std::cout << "Flyweight: Displaying shared (" << *shared_state_ << ") and unique (" << unique_state << ") state.";

}

3;

Finally, we implement the FlyWeight Factory class:

[**

* The Flyweight Factory creates and manages the Flyweight objects

* It ensures that flyweights are shared correctly When the client

* requests a flyweight, the factory either returns an existing

* instance or creates a new one, if it doesn't exist yet

*/

class FlyweightFactory

{

/**

*/

private:

std: :unordered_map<std::string, Flyweight> flyweights_;

[**

* Returns a Flyweight's string hash for a given state

*/

std::string GetKey(const SharedState &ss) const

{

return ss.brand_ + "_" + ss.model_ + "_" + ss.color_;

+

public:

FlyweightFactory(std::initializer_list<SharedState> share states)

{

Trang 10

[**

* Returns an existing Flyweight with a given state or creates a new one for (const SharedState &ss : share_states)

{

(this->GetKey(ss), Flyweight (&ss)));

Flyweight GetFlyweight (const SharedState &shared_state)

{

}

if (this->flyweights_.find(key) == this->flyweights_.end())

{

std::cout << "FlyweightFactory: Can't find a flyweight, creating new one.";

Flyweight (&shared_state)));

else

std::cout << "FlyweightFactory: Reusing existing flyweight.\n";

}

return this->flyweights_.at(key) ;

void ListFlyweights() const

{

size_t count = this->flyweights_.size();

std::cout << "\nFlyweightFactory: I have " << count << " flyweights:"; for (std: :pair<std::string, Flyweight> pair : this->flyweights_)

{

std::cout << pair.first << "\n";

void AddCarToPoliceDatabase(

FlyweightFactory &ff, const std::string &plates, const std::string &owner, const std::string &brand, const std::string &model, const std::string &color)

Trang 11

6T std::cout << "\nClient: Adding a car to database.\n";

m +

So we have used the flyweight pattern to solve this problem, let see how it work:

1 (**

4 */

7 {

10 {"BMW", "M5", "red"}, {"BMW", "X6", "white"}});

19

28

Here is the output of the above code:

10

Trang 12

FlyweightFactory: I have 5 flyweights:

BMW_X6_white

Mercedes Benz_C500_red

Mercedes Benz_C300_black

BMW_M5_red

Client: Adding a car to database

FlyweightFactory: Reusing existing flyweight

Flyweight: Displaying shared ([ BMW , M5 , red ]) and unique ([ CL234IR , James Doe ])

state

Client: Adding a car to database

FlyweightFactory: Can't find a flyweight, creating new one

Flyweight: Displaying shared ([ BMW , X1 , red ]) and unique ([ CL234IR , James Doe ])

state

FlyweightFactory: I have 6 flyweights:

BMW_X1_red

Mercedes Benz_C300_black

BMW_X6_white

Mercedes Benz_C500_red

BMW_M5_red

Here are some popular application of flyweight pattern in real world:

*« Text Processing - A text editor or word processor has to deal with a large number of similar objects like characters The Flyweight pattern allows storing each unique character once and sharing instances of duplicate characters

« File Systems - File systems have to store and retrieve a large number of similar small files like images, audio/video clips Flyweight reduces memory overhead of duplicate files

« Operating System Interfaces - In computer, OS (Operating System) have to display the same icons in different addresses Flyweight pattern helps OS display those by sharing resources with the root files

« Graphics Rendering - Computer games have to render large numbers of similar graph- ical objects like trees, buildings etc Flyweight stores unique graphic objects and shares instances of duplicates for rendering multiple objects in different positions, situations with only one unique object loaded on memory

« Cache Systems - Systems with large in-memory caches like databases use Flyweight to store cached objects more efficiently by sharing duplicates

* Web data managing - Many platforms such as YouTube, Facebook, etc have to store

a large number of data such as images, audio/videos, text, etc Flyweight pattern helps users access their resources in their data pool instead of downloading them to use

11

Ngày đăng: 26/09/2024, 17:26

w