Common design patterns in Game Development

Source: Internet
Author: User
Transferred to the Internet. The address is not recorded
Use design patterns to improve Program Library reuse is required for large-scale program project development. However, 23 standard design patterns are mentioned in the design patterns overview of the four-person gang, which are hard to remember, and some design patterns are more suitable for application development, there is no significant value to the Engine Design of game projects. Based on experience, after careful selection, I would like to record some design patterns that I think are useful for later use.

I. Observer observer

The design intent and function of the observer is to create a dependency between the object and the object. When one of the objects changes, it notifies you of the change to the object in which the link is created, enabling automatic notification updates.

The applicable environments of observers in the game include:

1: UI control management class. When all of our GUI controls use the observer mode, any user interface-related operations and changes will be notified of their associated objects-our UI event machine.

2: animation manager. Most of the time, when playing an animation, we are very interested in its frame. At this time, we set a framelister object to monitor it, it is necessary to handle events that we care about.

Observer pseudoCode:

//-------------------------------------------------------------------? -----------------------------------

// Target class of the observed object

Class subject

{

// Bind an observer attach (observer) to the target );

// Unbind an observer deleteattach (observer );

// If the target changes, all observers are notified, but no changes are passed.

Notity ()

{

For (... Traverse the entire observerlist ...)

{Pobserver-> Update ();}

}

// The interface exposed to the observer so that the observer can obtain the getstate () changes to the class ();

}

// Configure //-------------------------------------------------------------------------------------------------------

// Observer/listener
Class observer

{

// Function exposed to the object's target class. When the Monitored object changes, it calls this function to notify the observer.

Void Update ()

{

Psubject-> getstate (); // obtain the listener object.

Todo: disposefun (); // different processing based on different States

}

}

// Configure //-------------------------------------------------------------------------------------------------------

Non-program language description:

A is a good friend of B and is very concerned about B's behavior. B is about to go out. At this time, a gave B an alarm and told B: "If you have something, immediately press this alarm to tell me .". As a result, B encountered a problem outside, and pressed the alarm (Update (), B knew that a had an error, so he investigated what troubles B encountered (getstate ()), when I knew that B was beaten, I immediately handled disposefun () and sent a group of men to help B fight.

Of course, there can be more than one person who cares about a, and C and D may be very concerned about A. So here, a stores a linked list of all people who care about it. When you are in trouble, send a notification to each person in turn.

Ii. Singleton
The design intent and function of the single-piece mode is to ensure that a class has only one instance and only one global access point is provided.

In the game, the single-piece mode is applicable:

1: All manger. Most popular engines have their shadows, such as soundmanager and particle manager.

2: Most factory base classes. This is not seen in most engines. In fact, if our parent class factory uses a unique instance, it will be very convenient for our subclass to expand.

Single-piece mode pseudocode:

// Configure //-------------------------------------------------------------------------------------------------------

{

Static mysingleton; // unique object.

Static instance () {return mysingleton;} // interface for external exposure

}

// Configure //-------------------------------------------------------------------------------------------------------

Iii. iterator

The design intent and function of the iterator is to provide a method to access each element in a composite aggregate object without exposing the internal representation of the object class.

In the game, applicable to the iterator mode: due to the popularity of STL, this design has been widely known, and we will inevitably aggregate it when managing all forms of resources, or list, or vector, we all need a tool to access it. The iterator is undoubtedly a powerful tool.

Iterator pseudo code:

//--------------? Bytes ----------------------------------------------------------------------------------------

// Iterator base class

Class iterator

{

Virtual first ();

Virtual next ();

Virtual end ();

Virtual currentitem (); // returns the current item information

}

// Configure //-------------------------------------------------------------------------------------------------------

// Aggregates the base class

Class itemaggregate

{

Virtual createiterator (); // create an iterator to access itself

}

//-----------------? Bytes -------------------------------------------------------------------------------------

// Instantiate the project combination

Class instanceitemaggregate: Public itemaggregate

{

Createiterator () {return New instanceiterator (this );}

}

// Configure //-------------------------------------------------------------------------------------------------------

4. Visitor mode Visitor:

Visitor design intent and role: when we want to add a function to a structure object, we can define a new operation on its elements without affecting the structure. (In fact, we only implement the Division of Operations on this element into each element's own class)

What is applicable to the visitor mode in the movie show is that a visitor is suitable for any static Complex Structure class. Here, the "relatively static Complex Structure class" means that the structure class has a wide variety of elements, complex types, and many corresponding operations, but the class is rarely changed, we can, operations on this structural element are independent to avoid contamination of these element objects.

1: for example, the scenario nodes managed in the scenario manager are very diverse and varied. For example, if there are root nodes in ogre and irrchit, the camera, lighting, mesh, and announcement versions are displayed, sound is a scene node. Each node type is different. Although everyone has a common method such as paint () and hide (), the method implementation form is different, when we need a unified interface for external calls, we may need such code.

Hide (object)

{If (Object = mesh) hidemesh (); If (Object = light) hidelight ();... }

If we need to add a new object type object, we have to modify the function. We can do this to make mesh and light all inherit from objects. They all implement a function, hide (), and then transform it

Mesh: Hide (visitor) {visitor. Hide (mesh );}

Light: Hide (visitor) {visitor. Hide (light );}

We only need object. Hide (visitor) {return visitor. Hide (object );}

In this way, we do not need to correct important functions, object. the hide (visitor) {} function can be permanently unchanged, but the disadvantage is also obvious, because extracting methods from the object collection structure means that each time we add an element, it must inherit from an abstract visitor class and implement all its functions. This is a huge workload.

Therefore, the visitor is only suitable for a large container that loads different objects, but also requires that the element nodes of the container should not be used when there are major changes. In addition, the visitor breaks down the OO idea.

Visitor pseudocode:

//-----------------------------------------------------------------------? -------------------------------

// Visitor Base Class

Class visitor

{

Virtual visitelement (){... }; // Write this method for each object to be accessed

Virtual visitelement (B ){... };

}

// Visitor instance

Class visitora

{

Visitelement (){... }; // The actual processing function

Visitelement (B ){... }; // The actual processing function

}

// Visitor instance B

Class visitorb

{

Visitelement (){... }; // The actual processing function

Visitelement (B ){... }; // The actual processing function

}

// Base class of the visitor

Class Element

{

Virtual accept (visitor); // receives visitors

}

// Instance

Class elementa

{

Accecpt (visitor v) {v-> visitelement (this) ;}; // call the handler function registered to the visitor

}

// Visitor instance B

Class elementb

{

Accecpt (visitor v) {v-> visitelement (this) ;}; // call the handler function registered to the visitor

}

// Configure //-------------------------------------------------------------------------------------------------------

5. Appearance mode fa? Ade

The design intent and function of the appearance mode is to separate the surface and the internal subset of the user contact. In fact, this pattern is a paper tiger. Then we can immediately read the pseudocode and find that this pattern is used too frequently.

The appearance mode needs to be used in the game: This is a lot more important.

1: platform independence. Cross-platform and cross-database function calls.

2: the same interface reads different resources.

3: Automatic hardware identification and processing system.

Appearance mode pseudocode

// Configure //-------------------------------------------------------------------------------------------------------

// Interface class used by the user

Class Interface

{

// The exposed function interface function has only one function, but the internal implementation calls two classes.

Void interfacefun ()

{
// Based on certain conditions, the underlying layer selects the or B method. Users do not need to care about underlying implementation

If (XXX)

{

Actuala-> fun ();

}

Else

{

Actualb-> fun ();

}

};

}

// The actual implementation is not exposed to the user

Class actuala

{

Void fun ();

}

// The actual implementation is not exposed to the user

Class actualb

{

Void fun ();

}

How about it, paper tiger? It looks like a deep name.

// Response //----------------------------------------------------------------------------------------------------? --

6. abstractfactory

The design intent and function of the abstract factory is to encapsulate an interface to create a series of correlated objects. However, you do not need to specify the specific class of the object when using the interface. From the Chinese name, it is easy to understand that it is a production factory for batch production.

Where abstract factories are used in the game: basically, there will be factories in any place with similar batch forms of sub-pieces. (In the following code, the concretefactory1 instance factory is the factory, and the abstract factory is just an abstract layer of the factory .)

1: for example, in terms of audio, an audio abstraction factory derives from different factories, including music factories and sound effects factories. In the Sound Factory, another method is used to create 3D sound nodes, and a method for creating common sound nodes. The end user only needs soundfactory-> create3dnode (pfilename); To create a node.

2: scene object.

3: rendering objects.

4: Wait ......

The relationship between the factory and the single-piece manager must be very close.

Abstract Factory pseudocode:

// Configure //-------------------------------------------------------------------------------------------------------

Class abstractproducta {}; // abstract product a base class
Class abstractproductb {}; // abstract product B Base Class

// Abstract Factory base class
Class abstractfactory
{
Public:
Virtual abstractproducta * createproducta () = 0; // create a producta
Virtual abstractproductb * createproductb () = 0; // create productb
};

Class producta1: Public abstractproducta {}; // instance 1 of product
Class produ? TA2: Public abstractproducta {}; // instance 2 of product

Class productb1: Public abstractproductb {}; // instance 1 of product B
Class productb2: Public abstractproductb {}; // instance 2 of product B

// Instance Factory 1

Class concretefactory1: Public abstractfactory
{
Virtual abstractproducta * createproducta () {return New producta1 ();}
Virtual abstractproductb * createproductb () {return New productb1 ();}
Static concretefactory1 * instance () {}// the instance factory tries its best to use the single-piece Mode
};

// Instance factory 2

Class concretefactory2: Public abstractfactory
{
Virtual AB? Tractproducta * createproducta () {return New producta2 ();}
Virtual abstractproductb * createproductb () {return New productb2 ();}
Static concretefactory2 * instance () {}// the instance factory tries its best to use the single-piece Mode
};

}

// Configure //-------------------------------------------------------------------------------------------------------

Client code:

Void main ()
{
Abstractfactory * pfactory1 = concretefactory1: instance ();
Abstractproducta * pproducta1 = pfactory1-> createproducta ();
? Abstractproductb * pproductb1 = pfactory1-> createproductb ();
Abstractfactory * pfactory2 = concretefactory2: instance ();
Abstractproducta * pproducta2 = pfactory2-> createproducta ();
Abstractproductb * pproductb2 = pfactory2-> createproductb ();
}

// snapshot

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.