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

seminar report state design pattern

11 0 0
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 đề State Design Pattern
Tác giả Nguyễn Hữu Quốc Thắng, Nguyễn Chính Thông, Phạm Trung Nghĩa, Nguyễn Đức Thọ
Trường học Vietnam National University Ho Chi Minh City
Chuyên ngành Computer Science
Thể loại Seminar Report
Năm xuất bản 2023
Thành phố Ho Chi Minh City
Định dạng
Số trang 11
Dung lượng 849,62 KB

Nội dung

This pattern is called a Finite-State Machine [ ]:2An abstract machine consisting of a set of states including the initial state, a setof input events, a set of output events, and a stat

Trang 1

VIETNAM NATIONAL UNIVERSITY HO CHI MINH CITY

UNIVERSITY OF SCIENCE

SEMINAR REPORT

STATE DESIGN PATTERN

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

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

Ho Chi Minh City, 16/12/2023

Trang 2

1.1 Problem 2 1.2 Limitations 4

2.1 Structure 5 2.2 Implementation 6

Trang 3

1 Introduction

1.1 Problem

Imagine we are writing a dictionary, and we want the user to be able to switch to different

“pages”, or modes of the app, such as a Word Search, Definition Search, View History, View Favorites, and Game Initially, one may decide to use a global variable to keep track of the state, and a switch statement, in order to switch to the mode that the user wants

One may write as follows [ ]:1

1 voidFrontendMain::start() {

2 // Logic to update the data for the current Page of the dictionary

3 switch(CurrentState::currentPage) {

4 casePage::DICT_WORD: {

5 word.update();

6 break;

7 }

8 casePage::DICT_DEF_SEARCH: {

9 def.update();

10 break;

11 }

12 casePage::DICT_FAVORITES: {

13 favorites.update();

14 break;

15 }

16 casePage::DICT_HISTORY: {

17 history.update();

18 break;

19 }

20 casePage::DICT_GAME: {

21 game.update();

22 break;

23 }

24 casePage::SINGLE_WORD_INFO: {

25 singleWordInfo.update();

26 break;

27 }

28 default:

29 break;

30 }

31

32 // Logic to draw the current Page of the dictionary

33 BeginDrawing();

2

Trang 4

34 {

35 ClearBackground(BG_COLOR_RGB);

36 switch(CurrentState::currentPage) {

37 casePage::DICT_WORD: {

38 word.draw();

39 break;

41 casePage::DICT_DEF_SEARCH: {

42 def.draw();

43 break;

45 casePage::DICT_FAVORITES: {

46 favorites.draw();

47 break;

49 casePage::DICT_HISTORY: {

50 history.draw();

51 break;

53 casePage::DICT_GAME: {

54 game.draw();

55 break;

57 casePage::SINGLE_WORD_INFO: {

58 singleWordInfo.draw();

59 break;

61 default:

62 break;

64

65 DrawTextureV(Resources::headerImage, {Header.x, Header.y}, WHITE);

66 DrawTextEx(Resources::titleFont,"THE DICTIONARY",

67 {500, Header.height / 2 - 30}, 50, 0, WHITE);

68 }

69 EndDrawing();

70 }

Trang 5

This pattern is called a Finite-State Machine [ ]:2

An abstract machine consisting of a set of states (including the initial state), a set

of input events, a set of output events, and a state transition function The function takes the current state and an input event and returns the new set of output events and the next state

To simplify the concept:

At any given moment, there’s a finite number of states that the program can be in Within these states, the program can control the behavior of the system Depending on the current state, the program may decide whether to switch to other certain states, based on a set of rules These rules, called transitions, are also finite and predetermined State machines are usually predetermined with conditional statements (if or switch) that selects the appropriate behavior depending on the current state of the object

1.2 Limitations

For a project that only has a handful of states, like this one, it would be fine However, once we begin to add more and more states into the project, it becomes unreadable and harder

to maintain

For this particular project, we’ll need to add both the update() and draw() method when

we add a new “page” to the project Imagine this, but a bunch of pages more, like a thesaurus,

or word origin, or word of the day! It gets hard to navigate around easily

Additionally, in the future, imagine we want to also add more features into the program Like a version that the user has to pay to access the mentioned features We’d need to implement a check to check if the user has a valid license

Or like a word history feature We’d need to check if we have a network connection in order

to serve the user the latest version of the history, or if we need to use a local version And so on

It’s hard to predict all of the possible states and transitions for a single program

4

Trang 6

2 Definition

The state pattern is a behavioral software design pattern that allows an object to alter its behavior when its internal state changes [ ] This pattern is close to the concept of finite-state3 machines

The state pattern is used in computer programming to encapsulate varying behavior for the same object, based on its internal state This can be a cleaner way for an object to change its behavior at runtime without resorting to conditional statements and thus improve maintainability

2.1 Structure

The State pattern typically consists of the following key components:

• Context: Context stores a reference to one of the concrete state objects and delegates to

it all state-specific work The context communicates with the state object via the state interface The context exposes a setter for passing it a new state object

• State: The State interface declares the state-specific methods These methods should make sense for all concrete states because you don’t want some of your states to have useless methods that will never be called

• Concrete States: Concrete States provide their own implementations for the state-specific methods To avoid duplication of similar code across multiple states, you may provide intermediate abstract classes that encapsulate some common behavior.State objects may store a backreference to the context object Through this reference, the state can fetch any required info from the context object, as well as initiate state transitions Both context and concrete states can set the next state of the context and perform the actual state transition by replacing the state object linked to the context

The interaction between these components can be summarized as follows:

• The context maintains a reference to the current state object

• The context delegates the execution of a method to the current state object

• The current state object performs the behavior associated with that state

• The current state object may modify the state of the context, transitioning it to a different state if necessary

The State pattern promotes the encapsulation of state-specific behavior into separate classes, enabling the context object to be more flexible and adaptable to different states It allows for the addition of new states without modifying the context, and it improves code maintainability

by keeping behavior related to each state in separate classes

Trang 7

2.2 Implementation

1 Decide what class will act as the context It could be an existing class which already has the state-dependent code; or a new class, if the state-specific code is distributed across multiple classes

2 Declare the state interface Although it may mirror all the methods declared in the context, aim only for those that may contain state-specific behavior

3 For every actual state, create a class that derives from the state interface Then go over the methods of the context and extract all code related to that state into your newly created class While moving the code to the state class, you might discover that it depends on private members of the context There are several workarounds:

• Make these fields or methods public

• Turn the behavior you’re extracting into a public method in the context and call it from the state class This way is ugly but quick, and you can always fix it later

• Nest the state classes into the context class, but only if your programming language supports nesting classes

4 In the context class, add a reference field of the state interface type and a public setter that allows overriding the value of that field

5 Go over the method of the context again and replace empty state conditionals with calls

to corresponding methods of the state object

6 To switch the state of the context, create an instance of one of the state classes and pass

it to the context You can do this within the context itself, or in various states, or in the client Wherever this is done, the class becomes dependent on the concrete state class that it instantiates

3 Example

To better understand how to implement the State design pattern, let’s look at a simple example of a simple state of a traffic light:

6

Trang 8

1 Decide on the class that will act as the context It could be an existing class that already has state-dependent code or a new class if the state-specific code is distributed across multiple classes In this example, let’s create a class called TrafficLight to represent a traffic light

2 Declare the state interface The interface should include methods that may contain state-specific behavior In this example, we can create an interface called LightState with methods like turnOn(), turnOff(), and changeState()

1 classLightState{

2 public:

3 virtualvoidturnOn() = 0;

4 virtualvoidturnOff() = 0;

5 virtualvoidchangeState() = 0;

6 };

3 Create concrete classes for each actual state by deriving them from the state interface Move the state-specific code from the context class into these newly created state classes

1 classRedState: publicLightState {

2 public:

3 voidturnOn()override{

4 cout <<"Red light is on"<< endl;

5 }

6

7 voidturnOff()override{

8 cout <<"Red light is off"<< endl;

9 }

10

11 voidchangeState()override{

12 cout <<"Changing state from red to green"<< endl;

13 // Switch to GreenState

14 context->setState(newGreenState(context));

15 }

16 };

17

18 classGreenState: publicLightState {

19 public:

20 voidturnOn()override{

Trang 9

25 cout <<"Green light is off"<< endl;

26 }

27

28 voidchangeState()override{

29 cout <<"Changing state from green to yellow"<< endl;

30 // Switch to YellowState

31 context->setState(newYellowState(context));

32 }

33 };

34

35 classYellowState: publicLightState {

36 public:

37 voidturnOn()override{

38 cout <<"Yellow light is on"<< endl;

39 }

40

41 voidturnOff()override{

42 cout <<"Yellow light is off"<< endl;

43 }

44

45 voidchangeState()override{

46 cout <<"Changing state from yellow to red"<< endl;

47 // Switch to RedState

48 context->setState(newRedState(context));

49 }

50 };

4 In the context class (TrafficLight), add a reference field of the state interface type and

a public setter that allows overriding the value of that field

1 classTrafficLight{

2 private:

3 LightState* state;

4

5 public:

6 voidsetState(LightState* newState) {

7 state = newState;

8 }

9

10 voidperformAction() {

11 state->turnOn();

12 state->changeState();

8

Trang 10

13 state->turnOff();

14 }

15 };

5 Now, to use the State design pattern, create an object of TrafficLight and set the initial state

1 intmain() {

2 TrafficLight trafficLight;

3

4 // Set initial state to RedState

5 trafficLight.setState(newRedState(&trafficLight));

6

7 // Perform actions

8 trafficLight.performAction();// RED -> GREEN

9 trafficLight.performAction();// GREEN -> YELLOW

10 trafficLight.performAction();// YELLOW -> RED

11

12 return0;

13 }

4 Real World Problems

• TV: ON or OFF

ON: can press any button on the remote control depending on current function of TV

OFF: can only press Power button on the remote control

• Phone: Silent, Vibration, Ringing

Silent: No sound, no vibration when upcoming call

Vibration: Only vibration …

Ringing: Sound + vibration …

• Traffic Light: R, Y, G

Each state, bulbs must release light with different wavelength, the timer must set

to a different period of time

Trang 11

5 Pros/Cons of State

• Pros:

In the State design pattern, an object’s behavior is the result of the function of its state, and the behavior gets changed at runtime depending on the state This removes the dependency on the if/else or switch/case conditional logic

Single Responsibility Principle Organize the code related to particular states into separate classes You may guarantee that each state has a clear and distinct duty

by encapsulating the behavior in multiple states, which can make your code easier

to maintain and alter

Open/Closed Principle Introduce new states without changing existing state classes

or the context

Simplify the code of the context by eliminating bulky state machine conditionals

• Cons:

Applying the pattern can be overkill if a state machine has only a few states or rarely changes

The State design pattern can be used when we need to change the state of the object

at runtime by inputting into it different subclasses of some State base class This circumstance is an advantage and disadvantage at the same time because we have

a clear separate State class with some logic and on the other hand the number of classes grows up

References

[1] N H Q Thang, L N Khoa, L P Minh, and N V H Thong, The Dictionary, CS163 Final Project, Aug 30, 2023 [Online] Available: https://github.com/Rookie001MC/Dictionary [2] Free Online Dictionary of Computing (Sep 22, 2001), [Online] Available: https://web archive.org/web/20171211180457/http://foldoc.org/finite+state+machine (visited on 12/06/2023)

[3] E Gamma, R Helm, R E Johnson, and J Vlissides, “Design Patterns, Elements of Resuable Object-Oriented Software,” in 2016, pp 305–313

10

Ngày đăng: 14/05/2024, 16:10

TÀI LIỆU CÙNG NGƯỜI DÙNG

TÀI LIỆU LIÊN QUAN

w