How to use the design pattern to design your football engine (Part 3 and Part 4)

Source: Internet
Author: User

Address: http://www.codeproject.com/KB/cpp/applyingpatterns2.aspx

Author:An 'oop 'madhusudanan

Translator: Lai Yonghao (Http://blog.csdn.net/lanphaday)

Solution Architect: How is your progress?

Stupid developer: Yes, I think I learned how to apply the observer mode to solve all problems.

Solution Architect: can a single model solve all problems?

Stupid developers: Isn't it enough?

Introduction

About this article

This is the second article in this series. Before reading this article, you should have read and understood the first article in this series, entitled

  • Learn how to use design patterns to design your football engine (part 1 and part 2)

In the first article, we discussed

  • What are patterns and how to use them?
  • How to support solution application modes
  • How to Use the observer model to solve our football Engine Design Problems

This article is a continuation of the previous article. Here we will discuss

  • Part 3: Apply the strategy model to solve design problems related to "team" and "team strategy"
  • Part 4: Use the decorator mode to solve the design problems related to "Player"

If you don't remember these design issues, you 'd better go back to the first article and try again.

Part 3

Apply the Strategy Mode

In this section, we will go deep into the policy mode and then apply this mode to solve the second design problem. As in the previous article, let's review our second design question here.

How can you remember that our second design question is:

  • Specific design problems: end users can change their team strategies during the game (for example, from attacking to defending)
  • Problem generalization: The algorithms (Team Strategy) used by the client (here the Team) can be changed independently.

As mentioned above, when the game goes on, we need to change the team's Strategy (for example, from attacking to defending ). Specifically, we need to share the team's strategy from the team.

We know that the Strategy mode can be used to solve the above design problems, because it can make the algorithms used by clients (such as teams) (such as team policies) change independently; let's take a look at how to use the strategy mode to solve this design problem.

Understanding the Strategy Mode

The Strategy Mode is very simple. The following is a UML diagram of the Strategy Mode:

Fig-strategy Pattern

How many parts does it contain?

  • Strategy)

This is an abstract class of an algorithm (policy). All specific algorithms are derived from it. In short, it provides a common interface for all specific algorithms (or specific policies. In other words, if class strategy has an abstract function named Foo (), then all specific policy classes should overload the Foo () function.

  • Concretestrategy)

This class is the place where we actually implement the algorithm, or it is the specific implementation of class strategy. For example, sort is a policy class that implements algorithms, and specific policies can be mergesort or quicksort.

  • Context)

Context can be configured by one or more policy classes. It is usually used by policy interfaces to access specific policy objects.

Apply the Strategy Mode

Now let's think about how to use the strategy mode to solve the problem.

Fig-solving our second design problem

Teamstrategy class includes the play function. attackstrategy and defendstrategy are specific implementations of teamstrategy. The team includes a strategy, which can be changed according to the situation of the game (for example, after winning several goals, the strategy is changed from an attack strategy to a defensive strategy ). When the playgame function of the team is used, it calls the play function of the current policy, which takes effect immediately and is clean.

The policy mode allows you to separate algorithms from class teams (such as team policies ).

Strategy Mode implementation

Teamstrategy (Strategy)

The code for teamstrategy-like execution is as follows:

'Strategy: The TeamStrategy class'This class provides an abstract interface 'to implement concrete strategy algorithmsPublic MustInherit Class TeamStrategy'AlgorithmInterface : This is the interface providedPublic MustOverride Sub Play ()End Class ' END CLASS DEFINITION TeamStrategy

Attackstrategy (concretestrategy)

The following code is a class attackstrategy derived from teamstrategy:

'ConcreteStrategy: The AttackStrategy class'This class is a concrete implementation of the'strategy class.Public Class AttackStrategyInherits TeamStrategy    'Overrides the Play function.     'Let us play some attacking game    Public Overrides Sub Play()        'Algorithm to attack        System.Console.WriteLine(" Playing in attacking mode")    End SubEnd Class ' END CLASS DEFINITION AttackStrategy

Defendstrategy (concretestrategy)

Below is the code for the defendstrategy class, which is also derived from teamstrategy:

'ConcreteStrategy: The DefendStrategy class'This class is a concrete implementation of the'strategy class.Public Class DefendStrategyInherits TeamStrategy    'Overrides the Play function.     'Let us go defensive    Public Overrides Sub Play()        'Algorithm to defend        System.Console.WriteLine(" Playing in defensive mode")    End SubEnd Class ' END CLASS DEFINITION DefendStrategy

Team (context)

The following is the code for a team. According to our design, a team can only have one strategy at a time:

'Context: The Team class'This class encapsulates the algorithmPublic Class Team    'Just a variable to keep the name of team    Private teamName As String    'A reference to the strategy algorithm to use    Private strategy As TeamStrategy    'ContextInterface to set the strategy    Public Sub SetStrategy(ByVal s As TeamStrategy)        'Set the strategy        strategy = s    End Sub    'Function to play    Public Sub PlayGame()        'Print the team's name        System.Console.WriteLine(teamName)        'Play according to the strategy        strategy.Play()    End Sub    'Constructor to create this class, by passing the team's name    Public Sub New(ByVal teamName As String)        'Set the team name to use later        Me.teamName = teamName    End SubEnd Class ' END CLASS DEFINITION Team

Combination

Create teams, set their strategies, and start the game. The following code is quite simple and has detailed comments.

'GameEngine class for demonstrationPublic Class GameEngine    Public Shared Sub Main()        'Let us create a team and set its strategy,        'and make the teams play the game        'Create few strategies        Dim attack As New AttackStrategy()        Dim defend As New DefendStrategy()        'Create our teams        Dim france As New Team("France")        Dim italy As New Team("Italy")        System.Console.WriteLine("Setting the strategies..")        'Now let us set the strategies        france.SetStrategy(attack)        italy.SetStrategy(defend)        'Make the teams start the play        france.PlayGame()        italy.PlayGame()        System.Console.WriteLine()        System.Console.WriteLine("Changing the strategies..")        'Let us change the strategies        france.SetStrategy(defend)        italy.SetStrategy(attack)        'Make them play again        france.PlayGame()        italy.PlayGame()        'Wait for a key press        System.Console.Read()    End SubEnd Class

Run

The output after running the program is as follows:

Part 4

Decorator Mode

In this section, we will talk about how to apply the decorator mode to solve the third design problem (if necessary, refer to the previous article ). This problem is related to the assignment of players' runtime responsibilities (such as forward and defender ).

You can consider creating a player class and then derive multiple sub-classes, such as forward, center, and defender, based on it. But it is not the best solution, as we have discussed earlier-a player can be a forward player at a certain moment, and another moment becomes a center. At least in our football engine, this is our design problem.

Specific design problems: players have additional responsibilities, such as power forward and defender, and can switch during operation.

Problem generalization: When subclass is not used, it is necessary to dynamically attach additional responsibilities (such as forward and center) to the object (here it refers to players ).

Understanding the decorator Mode

The decorator mode can dynamically add roles to objects, making it a perfect choice outside of subclass. The following is a UML diagram of the decorator mode:

Fig-decorator pattern

This mode consists of the following parts:

  • Component)

The Class component declares an abstract interface for the component. We can attach additional responsibilities to these components.

  • Specific components (concretecomponent)

Class concretecomponent is the specific implementation of Class component, which truly defines an additional responsibility that can be attached.

  • Decorator)

The class decorator inherits from the class component, which means that it inherits all the interfaces (functions, attributes, etc.) of the component and holds a reference to the object inherited from the component class. In fact, a specific decorator Can even hold references from other decorers (because class decorator is derived from Class component ).

  • Concrete decorator)

This class is really responsible for components.

Decorator Mode

Now let's take a look at how to apply the decorator mode to solve player-related design problems.

Fig-solving our third design problem

We can see that the class player inherits two specific components-goalkeeper and fieldplayer. There are also three specific decorator-forward, midfielder, and defender. A team has 11 players and a goalkeeper (Note: I am wrong. It should be 10 players. I will not point out the same mistakes in the following article ). Our design problem is that we need to assign a role like forward and guard to players during operation. Although we only have 11 players, there may be 11 forward and 11 center players at the same time, because one player can be both a forward and a center. By assigning multiple roles to players and exchanging their roles, we can plan our best game strategy.

For example, you can assign a forward modifier to a player at a certain time of the game so that the player can sprint and shot.

To add additional responsibilities to a specific component, You can first create a specific component and assign it to the modifier as a reference. For example, you can create a full-site player and a center decoration. Assigning a full-site player to the center decoration can increase the center's responsibilities. Finally, if you want to, you can assign the same player to the striker. The gameengine module in the sample code provides a good explanation of the decorator mode.

Next let's take a look at its implementation. The Code has added a lot of comments.

Decorator mode implementation

Player (Component)

The implementation of the class player is as follows:

' Component: The Player classPublic MustInherit Class Player    'Just give a name for this player    Private myName As String    'The property to get/set the name    Public Property Name() As String        Get            Return myName        End Get        Set(ByVal Value As String)            myName = Value        End Set    End Property    'This is the Operation in the component    'and this will be overrided by concrete components    Public MustOverride Sub PassBall()End Class ' END CLASS DEFINITION Player

Fieldplayer (concretecomponent)

The following describes how to implement fieldplayer:

' ConcreteComponent : Field Player class'This is a concrete component. Later, we will add additional responsibilities'like Forward, Defender etc to a field player.Public Class FieldPlayerInherits Player    'Operation: Overrides PassBall operation    Public Overrides Sub PassBall ()        System.Console.WriteLine(_          " Fieldplayer ({0}) - passed the ball", _          MyBase.Name)    End Sub    'A constructor to accept the name of the player    Public Sub New(ByVal playerName As String)        MyBase.Name = playerName    End SubEnd Class ' END CLASS DEFINITION FieldPlayer

Goalkeeper (concretecomponent)

The following is the implementation of the goalkeeper class:

' ConcreteComponent : GaolKeeper class'This is a concrete component.'Later, we can add additional responsibilities'to this class if required.Public Class GoalKeeperInherits Player    'Operation: Overriding the base class operation    Public Overrides Sub PassBall ()    System.Console.WriteLine(" GoalKeeper " & _       "({0}) - passed the ball", MyBase.Name)    End Sub    'A constructor to accept the name of the player    Public Sub New(ByVal playerName As String)        MyBase.Name = playerName    End SubEnd Class ' END CLASS DEFINITION GoalKeeper

Playerrole (decorator)

The following is the implementation of the playerrole class:

'Decorator: PlayerRole is the decoratorPublic Class PlayerRoleInherits player    'The reference to the player    Protected player As player    'Call the base component's function    Public Overrides Sub PassBall()        player.PassBall()    End Sub    'This function is used to assign a player to this role    Public Sub AssignPlayer(ByVal p As player)        'Keep a reference to the player, to whom this        'role is given        player = p    End SubEnd Class ' END CLASS DEFINITION PlayerRole

Forward (concretedecorator)

The following is the implementation of the forward class:

'ConcreteDecorator: Forward class is a Concrete implementation'of the PlayerRole (Decorator) classPublic Class ForwardInherits PlayerRole    'Added Behavior: This is a responsibility exclusively for the Forward    Public Sub ShootGoal()        System.Console.WriteLine(" Forward ({0}) - " & _           "Shooted the ball to goalpost", _          MyBase.player.Name)    End SubEnd Class ' END CLASS DEFINITION Forward

Midfielder (concretedecorator)

The following is the implementation of the class midfielder:

'ConcreteDecorator: MidFielder class is a Concrete implementation'of the PlayerRole (Decorator) classPublic Class MidFielderInherits PlayerRole    'AddedBehavior: This is a responsibility exclusively for the Midfielder    '(Don't ask me whether only mid filders can dribble the ball - atleast    'it is so in our engine)    Public Sub Dribble()        System.Console.WriteLine(_          " Midfielder ({0}) - dribbled the ball", _          MyBase.player.Name)    End SubEnd Class ' END CLASS DEFINITION Midfielder

Defender (concretedecorator)

The following is the implementation of the Defender class:

'ConcreteDecorator: Defender class is a Concrete implementation'of the PlayerRole (Decorator) classPublic Class DefenderInherits PlayerRole    'Added Behavior: This is a responsibility exclusively for the Defender    Public Sub Defend()        System.Console.WriteLine(_          " Defender ({0}) - defended the ball", _          MyBase.player.Name)    End SubEnd Class ' END CLASS DEFINITION Defender

Combination

'Let us put it togetherPublic Class GameEnginePublic Shared Sub Main()    '-- Step 1:     'Create few players (concrete components)    'Create few field Players    Dim owen As New FieldPlayer("Owen")    Dim beck As New FieldPlayer("Beckham")    'Create a goal keeper    Dim khan As New GoalKeeper("Khan")    '-- Step 2:     'Just make them pass the ball     '(during a warm up session ;))    System.Console.WriteLine()    System.Console.WriteLine(" > Warm up Session... ")    owen.PassBall()    beck.PassBall()    khan.PassBall()    '-- Step 3: Create and assign the responsibilities    '(when the match starts)    System.Console.WriteLine()    System.Console.WriteLine(" > Match is starting.. ")    'Set owen as our first forward    Dim forward1 As New Forward()    forward1.AssignPlayer(owen)    'Set Beckham as our midfielder    Dim midfielder1 As New MidFielder()    midfielder1.AssignPlayer(beck)    'Now, use these players to do actions    'specific to their roles    'Owen can pass the ball    forward1.PassBall()    'And owen can shoot as well    forward1.ShootGoal()    'Beckham can pass ball    midfielder1.PassBall()    'Beckham can dribble too    midfielder1.Dribble()    ' [ Arrange the above operations to some meaningfull sequence, like    ' "Beckham dribbled and passed the ball to owen and owen shooted the    ' goal   - just for some fun ]"    '-- Step 4: Now, changing responsibilities    '(during a substitution)    'Assume that owen got injured, and we need a new player    'to play as our forward1    System.Console.WriteLine()    System.Console.WriteLine(" > OOps, Owen " _        "got injured. " & _       "Jerrard replaced Owen.. ")    'Create a new player    Dim jerrard As New FieldPlayer("Jerrard")    'Ask Jerrard to play in position of owen    forward1.AssignPlayer(jerrard)    forward1.ShootGoal()    '-- Step 5: Adding multiple responsibilities    '(When a player need to handle multiple roles)    'We already have Beckham as our midfielder.     'Let us ask him to play as an additional forward    Dim onemoreForward As New Forward()    onemoreForward.AssignPlayer(beck)    System.Console.WriteLine()    System.Console.WriteLine(" > Beckham has " & _            "multiple responsibilities.. ")    'Now Beckham can shoot    onemoreForward.ShootGoal()    'And use his earlier responsibility to dribble too    midfielder1.Dribble()    'According to our design, you can attach the responsibility of    'a forward to a goal keeper too, but when you actually     'play football, remember that it is dangerous      'Wait for key press    System.Console.Read()End SubEnd Class

Run

Below is the output of the running program

Conclusion

In this article, we have discussed

  • Mode and Its Implementation
  • Mode and Its Implementation

So much for now. In fact, it is the code project community's support for my previous article that encouraged me to write this article. Thank you for your support and encouragement!

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.