Design Your Soccer Engine, and Learn How To Apply Design Patterns (Observer, Decorator, Strategy and Builder Patterns) - Part I and II

This article is expected to (1) Introduce patterns to you in a simple, human readable way (2) Train you how to really identify and apply patterns (3) Demonstrate step by step methods to solve a design problem using patterns

The related zip file includes the code, UML designs (in Visio format) etc. After reading this article, you may download and extract the zip file - using a program like Winzip - to play with the source code.

Even with out much knowledge about design patterns, designers and developers tend to reuse class relationships and object collaborations to simplify the design process. In short, "A Design pattern consists of various co-operating objects (classes, relationships etc)". They provide solutions for common design problems. More than anything else, they offer a consistent idiom for designers and programmers to speak about their design. For example, you can tell a friend that you used a 'Builder' pattern for addressing some design specifications in your project.

A consistent classification of patterns for common design problems are provided by Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides [also known as the Gang of Four (GOF)]. The Gang of Four (GOF) patterns are generally considered the foundation for all other patterns.

The basic principle of using patterns is reusability. Once a problem is address some way, you are not really expected to re-invent the wheel if you properly understand the concept of pattern centric software engineering. Here are some important points to remember about design patterns.

A Design Pattern is not code. It is in fact an approach or a model that can be used to solve a problem.

Design Patterns are about design and interaction of objects and they provide reusable solutions for solving common design problems.

A Design Pattern is normally represented with the help of a UML diagram.

Some real hands on experience with patterns may provide you a better idea!!

You are working with a popular computer game developing company, and they made you the Solution Architect of one of their major projects - a Soccer (Football) Game Engine (Nice, huh?). Now, you are leading the process of designing the entire Football game engine, and suddenly you have a lot of design considerations, straight away. Let us see

First of all, you need to identify the objects you use in your game engine. For this, you should visualize how the end user is going to use the system. Let us assume that the end user is going to operate the game in the following sequence (let us keep things simple).

Start the game

Select two teams

Add or remove players to/from a team

Pick a play ground

Start the game

Your system may have a number of PlayGrounds in it, a number of Teams etc. To list a few real world objects in the system, you have

Player who play the soccer

Team with various players in it

Ball which is handled by various players.

PlayGround where the match takes place.

Referee in the ground to control the game.

Also, you may need some logical objects in your game engine, like

Game which defines a football game, which constitutes teams, ball, referee, playground etc

GameEngine to simulate a number of games at a time.

TeamStrategy to decide a team's strategy while playing

So, here is a very abstract view of the system. The boxes represent classes in your system, and the connectors depicts 'has' relationships and their multiplicity. The arrow head represents the direction of reading. I.e, a GameEngine has (can simulate) Games. A Game has (consists of) three referees, one ball, two teams, and one ground. A team can have multiple players, and one strategy at a time.

Their behavior when they interact each other, to formulate the design specifications.

First of all, you have to write down a minimum description of your soccer engine, to identify the design problems. For example, here are few design problems related to some of the objects we identified earlier.

Ball

When the position of a ball changes, all the players and the referee should be notified straight away.

Team and TeamStrategy

When the game is in progress, the end user can change the strategy of his team (E.g., From Attack to Defend)

Player

A player in a team should have additional responsibilities, like Forward, Defender etc, that can be assigned during the runtime.

PlayGround

Each ground constitutes of gallery, ground surface, audience, etc - and each ground has a different appearance.

So now, let us see how to identify the patterns, to address these design problems.

First of all, take the specifications related to the ball. You need to design a framework such that when the state (position) of the ball is changed, all the players and the referee are notified regarding the new state (position) of the ball. Now, let us generalize the problem

Specific Design Problem: "When the position of a ball changes, all the players and the referee should be notified straight away."

Problem Generalized: "When a subject (in this case, the ball) changes, all its dependents (in this case, the players) are notified and updated automatically."

Once you have such a design problem, you refer the GOF patterns - and suddenly you may find out that you can apply the 'Observer' pattern to solve the problem.

<TABLE id=AutoNumber1 style="BORDER-COLLAPSE: collapse" borderColor=#111111 cellPadding=2 width="100%" bgColor=#ffffcc border=1>
Observer Pattern: Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.

In this case, we used this pattern because we need to notify all the players, when the position of the ball is changed.

Next, we have to address the specifications related to the team and team strategy. As we discussed earlier, when the game is in progress, the end user can change the strategy of his team (E.g., From Attack to Defend). This clearly means that we need to separate the Team's Strategy from the Team that uses it.

Specific Design Problem: "When the game is in progress, the end user can change the strategy of his team (E.g., From Attack to Defend)"

Problem Generalized: "We need to let the algorithm (TeamStrategy) vary independently from clients (in this case, the Team) that use it."

Then, you can chose the 'Strategy' pattern to address the above design problem.

<TABLE id=AutoNumber1 style="BORDER-COLLAPSE: collapse" borderColor=#111111 cellPadding=2 width="100%" bgColor=#ffffcc border=1>
Strategy Pattern: Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it.

Now, let us address the design specifications related to the player. From our problem definition, it is clear that we need to assign responsibilities (like forward, defender etc) to each player during run time. At this point, you can think about sub classing (i.e, inheritance) - by creating a player class, and then inheriting classes like Forward, Defender etc from the base class. But the disadvantage is that, when you do sub classing, you cannot separate the responsibility of an object from its implementation.

I.e, In our case, sub classing is not the suitable method, because we need to separate the responsibilities like 'Forward', 'Midfielder', 'Defender' etc from the Player implementation. Because, a player can be a 'Forward' one time, and some other time, the same player can be a 'Midfielder'.

Specific Design Problem: "A player in a team should have additional responsibilities, like Forward, Defender etc, that can be assigned during the runtime."

Problem Generalized: "We need to attach additional responsibilities (like Forward, Midfielder etc) to the object (In this case, the Player) dynamically, with out using sub classing"

Then, you can chose the 'Decorator' pattern to address the above design problem.

If you take a look at the specifications of Ground, we see that a ground's appearance is decided by various sub units like gallery, surface of the ground, audience etc. The appearance of the ground may vary, according to these sub units. Hence, we need to construct the ground in such a way that, the construction of the ground can create different representations of the ground. I.e, a ground in Italy may have different gallery structure and surface when compared to a ground in England. But, the game engine may create both these grounds by calling the same set of functions.

Specific Design Problem: "Each ground constitutes of gallery, ground surface, audience, etc - and each ground has a different appearance."

Problem Generalized: "We need to separate the construction of an object (ground) from its representation (the appearance of the ground) and we need to use the same construction process to create different representations."

<TABLE id=AutoNumber3 style="BORDER-COLLAPSE: collapse" borderColor=#111111 cellPadding=2 width="100%" bgColor=#ffffcc border=1>
Builder Pattern: Separate the construction of a complex object from its representation so that the same construction process can create different representations.

Now, you can chose the 'Builder' pattern to address the above design problem.

Part II

<FONT color=#990000>Solution Architect: "I asked you to learn about patterns"

<FONT color=#990000>Dumb Developer: "Yes, now I can develop a football engine using patterns"

<FONT color=#990000>Solution Architect: "Huh? What do you mean? !@@#!"

This class provides an interface for attaching and detaching observers. Subject class also holds a private list of observers. Functions in Subject class are

<FONT color=#990000>Attach - To add a new observer to the list of observers observing the subject

<FONT color=#990000>Detach - To remove an observer from the list of observers observing the subject

<FONT color=#990000>Notify- To notify each observer by calling the Update function in the observer, when a change occurs.

ConcreteSubject

This class provides the state of interest to observers. It also sends a notification to all observers, by calling the Notify function in its super class (i.e, in the Subject class). Functions in ConcreteSubject class are

<FONT color=#990000>GetState - Returns the state of the subject

Observer

This class defines an updating interface for all observers, to receive update notification from the subject. The Observer class is used as an abstract class to implement concrete observers

<FONT color=#990000>Update - This function is an abstract function, and concrete observers will over ride this function

ConcreteObserver

This class maintains a reference with the subject, to receive the state of the subject when a notification is received.

<FONT color=#990000>Update - This is the overridden function in the concrete class. When this function is called by the subject, the ConcreteObserver calls the GetState function of the subject to update the information it have about the subject's state.

Now, let us see how this pattern can be adapted to solve our specific problem. This will give you a better idea.

Fig 3 - Solving Our First Design Problem

When we call the SetBallPositionfunction of the ball to set the new position, it inturn calls the Notify function defined in the Ball class. The Notify function iterates all observers in the list, and invokes the Update function in each of them. When the Update function is invoked, the observers will obtain the new state position of the ball, by calling the GetBallPosition function in the Foot ball class.

FootBall (ConcreteSubject)

The implementation of FootBall class is shown below.

' ConcreteSubject : The FootBall Class
PublicClass FootBall
Inherits Ball
'State: The position of the ball
Private myPosition As Position
'This function will be called by observers to get current position
PublicFunction GetBallPosition() As Position
Return myPosition
EndFunction'Some external client will call this to set the ball's position
PublicFunction SetBallPosition(ByVal p As Position)
myPosition = p
'Once the position is updated, we have to notify observers
NotifyObservers()
EndFunction'Remarks: This can also be implemented as a get/set property
EndClass' END CLASS DEFINITION FootBall

Player (ConcreteObserver)

The implementation of Player class is shown below. Player is inherited from IObserver class

' ConcreteObserver: The Player Class
'Player inherits from IObserver, and overrides Update method
PublicClass Player
Inherits IObserver
'This variable holds the current state(position) of the ball
Private ballPosition As Position
'A variable to store the name of the player
Private myName AsString'This is a pointer to the ball in the system
Private ball As FootBall
'Update() is called from Notify function, in Ball class
PublicOverridesSub Update ()
ballPosition = ball.GetBallPosition()
System.Console.WriteLine("Player {0} say that the ball is at {1},{2},{3} ", _
myName, ballPosition.X, ballPosition.Y, ballPosition.Z)
EndSub'A constructor which allows creating a reference to a ball
PublicSubNew(ByRef b As FootBall, ByVal playerName AsString)
ball = b
myName = playerName
EndSubEndClass' END CLASS DEFINITION Player

Referee (ConcreteObserver)

The implementation of Referee class is shown below. Referee is also inherited from IObserver class

' ConcreteObserver : The Referee Clas
PublicClass Referee
Inherits IObserver
'This variable holds the current state(position) of the ball
Private ballPosition As Position
'This is a pointer to the ball in the system
Private ball As FootBall
'A variable to store the name of the referee
Private myName AsString'Update() is called from Notify function in Ball class
PublicOverridesSub Update()
ballPosition = ball.GetBallPosition()
System.Console.WriteLine("Referee {0} say that the ball is at {1},{2},{3} ", _
myName, ballPosition.X, ballPosition.Y, ballPosition.Z)
EndSub'A constructor which allows creating a reference to a ball
PublicSubNew(ByRef b As FootBall, ByVal refereeName AsString)
myName = refereeName
ball = b
EndSubEndClass' END CLASS DEFINITION Referee

Putting It All Together

Now, let us create a ball and few observers. We will also attach these observers to the ball, so that they are notified automatically when the position of the ball changes. The code is pretty self explanatory.

Running the project

With respect to purpose, patterns are classified to Creational, Structural and Behavioral. For example,

The Observer pattern we just learned is a behavioral pattern (because it help us model the behavior and interactions of objects)

The Builder pattern is a creational pattern (because it details how an object can be created in a particular way) and so on.

Here is the complete classification diagram.

I hope this article

May help you to understand how to use design patterns.

May help you some way to apply patterns in your projects

May help you to give a brief talk about patterns to your friends :)

And finally, if you have strokes in your head (a sign of great programmers <IMG alt=:) src="http://www.codeproject.com/script/images/smiley_smile.gif"> ) - I'll recommend an Art Of Living Part I workshop for you (See http://www.artofliving.org/courses.html ). It is an interactive workshop of 18 hours spread over 6 days. As it did for me, I hope that it may help you to find the right balance between your work and life - to improve the clarity of your mind, and to improve the quality of your life. You can get in touch with them here - http://www.artofliving.org/centers/main.htm

Here, MustInherit Keyword is been used while createing the IObserver Interface. Now Interface is always abstract and does not have body and the calling class wil implement the Interface, not Inherit. Please correct me if I am wrong.

I am starting to work with patterns and i have to ask: Can you write a short and general idea on how to apply the observer pattern on a game when the players are on the Web? Suppose that each player have an IP-Address and a name.

This is a really great article. I read this and the other two parts in your blog

I didn't find the builder pattern and I wished to be able to read it as well, however I'm still finding a free time today, to read the provider.

Got my 5.

By the way, could you please name your references, or perhaps suggest a book. I asked this in the Lounge and many guys introduced the main book: 'Design patterns' and another one: 'Object Primer'. Thanks a lot.

// "Life is very short and is very fragile also." Yanniwhile (I'm_alive){ cout<<"I love programming.";}

I'm VB.Net leisure programmer, former Pascal/FORTRAN/C/C++/VBx programmer for work and back to dev for a game project called Stars of Call.

I found your article very interesting, as it allowed me to formalize some things we do in .Net without thinking too much about them. Best example events. As some said in comments, they're one of many possible implementations of the Observer Pattern.

It'll help me as conceptual tools when I go into further design steps for coding my engine. I already recognized the Strategy, Decorator and Builder patterns in some objects I've already designed and it'll help me to streamline them and better design other objects.

I don't want to be one of the beggers of "can you post this for my language" people. But since it is listed in the C# section and contains only VB code: could you please either add C# code or remove this article from that section?

I would second this motion. The article was interesting, and still good, until I got to the VB.NET code. I don't want to start a flame war, but I have yet to meet the VB programmer who can understand and apply proper OO concepts. Just my experience and opinion.

Haha, that is why I wrote this article regarding OOP concepts in VB.NET - You can read the article VB.NET OOP Concepts[^] - Having said that, you can still generate C# code from the Visio diagrams in the code

This is a good explanation of the Observer pattern and overview of some others, but I had hoped for something more about identifying problems and selecting patterns, rather than just the patterns and implementation.

For example, you begin with saying that the Player objects need to be notified when the ball position changes - but nowhere in the design discussion do you say who changes the ball position, when, or why the ball even needs to have its position as a property (as opposed to the field keeping the ball position, another plausible alternative). One can view the position of the ball as being a property of the ball, but it can also be viewed as a relationship between the ball and the field. These are the sorts of questions that make the design problem hard.

In adding the balls position as an attribute of player and referee you have violated the OO principles of Information Expert, Low Coupling and High Cohesion.

Why do these objects need the responsibility to store the position of the ball. Surely they need to store their own position, and carry out an action based on their position gleaming the ball position from either the ball or the object that contains the ball e.g. Pitch. The responsibility for these actions could fall on the Player but if the Team strategy is likely to affect the result of an action e.g. in defensive mode the player responds to the kick action by kicking the ball up the field, whereas in attacking mode the player passes to his colleague. Then we need to use polymorphism to abstract the actions and load a defensive or attacking Action object based on strategy. This in some way violates information expert but it gets over it because other patterns are enhanced.

I am still getting to grips with all this GRASP stuff myself so apologies if Im talking rubbish. Somone will soon come along and tell me and it will probably be one of my colleagues.

Great example of GOF, just thought I would add my 2 pence just to help me understand these nutty principles if anything else.

I suggest Head First Design Patterns by Eric Freeman and Elisabeth Freeman. It uses the same type of example, walking the reader through the application of many design patterns. ISBN: 0-596-00712-4. Published by O'Reilly.