`
wgcode
  • 浏览: 593907 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

游戏开发中常用的设计模式

阅读更多

使用设计模式来提高程序库的重复利用性是大型程序项目开发必须的。但是在“四人帮”的设计模式概述中提到了23种标准设计模式,伍但难以记住,而且有些设计模式更多的适用于应用程序开发,对游戏项目引擎设计并没有很多的利用价值。根据经验,精挑细选后,笃志在这里记录一些自认为有利用价值的设计模式,以便之后自己设计时使用。



一:观察者Observer


观察者的设计意图和作用是: 它将对象与对象之间创建一种依赖关系,当其中一个对象发生变化时,它会将这个变化通知给与其创建关系的对象中,实现自动化的通知更新。



游戏中观察者的适用环境有: 

1:UI控件管理类。当我们的GUI控件都使用观察者模式后,那么用户的任何界面相关操作和改变都将会通知其关联对象-----我们的UI事件机。

2:动画管理器。很多时候我们在播放一个动画桢的时候,对其Frame有很大兴趣,此时我们设置一个FrameLister对象对其进行监视,获得我们关心的事件进行处理是必须的。



观察者伪代码:

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

// 被观察对象目标类

Class Subject

{

// 对本目标绑定一个观察者 Attach( Observer ); 

// 解除一个观察者的绑定 DeleteAttach( Observer ); 

// 本目标发生改变了,通知所有的观察者,但没有传递改动了什么

Notity()

{

For ( …遍历整个ObserverList …)

{ pObserver ->Update(); }

}

// 对观察者暴露的接口,让观察者可获得本类有什么变动GetState(); 

}

//-------------------------------------------------------------------------------------------------------

// 观察者/监听者类
Class Observer

{

// 暴露给对象目标类的函数,当监听的对象发生了变动,则它会调用本函数通知观察者 

Void Update () 

{ 

pSubject ->GetState(); // 获取监听对象发生了什么变化 

TODO:DisposeFun(); // 根据状态不同,给予不同的处理

}

}

//-------------------------------------------------------------------------------------------------------



非程序语言描述:

A是B的好朋友,对B的行为非常关心。B要出门,此时A给了B一个警报器,告诉B说:“如果你有事,立刻按这个警报器告诉我。”。结果B在外面遇上了麻烦,按下警报器(Update()),B就知道A出了事,于是就调查一下B到底遇到了什么麻烦(GetState()),当知道B原来是因为被人打了,于是立刻进行处理DisposeFun(),派了一群手下帮B打架。

当然关心A的人可以不止一个,C,D可能也对A很关心,于是A这里保存一个所有关心它的人的链表,当遇到麻烦的时候,轮流给每个人一份通知。



二:单件模式Singleton
单件模式的设计意图和作用是: 保证一个类仅有一个实例,并且,仅提供一个访问它的全局访问点。



游戏中适用于单件模式的有: 

1:所有的Manger。在大部分的流行引擎中都存在着它的影子,例如SoundManager, ParticeManager等。

2:大部分的工厂基类。这一点在大部分引擎中还是见不到的,实际上,我们的父类工厂采用唯一实例的话,我们子类进行扩展时也会有很大方便。



单件模式伪代码:

//-------------------------------------------------------------------------------------------------------

{

Static MySingleton; // 单件对象,全局唯一的。

Static Instance(){ return MySingleton; } // 对外暴露接口

}

//-------------------------------------------------------------------------------------------------------



三:迭代器Iterator


迭代器设计意图和作用是: 提供一个方法,对一个组合聚合对象内各个元素进行访问,同时又不暴露该对象类的内部表示。



游戏中适用于迭代器模式的有: 因为STL的流行,这个设计已经广为人知了,我们对任何形式的资源通一管理时,不免会将其聚合起来,或者List,或者Vector,我们都需要一个对其进行访问的工具,迭代器无疑是一个利器。



迭代器伪代码:

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

// 迭代器基类

Class Iterator

{

Virtual First(); 

Virtual Next(); 

Virtual End(); 

Virtual CurrentItem(); // 返回当前Item信息

}

//-------------------------------------------------------------------------------------------------------

// 聚合体的基类

Class ItemAggregate

{

Virtual CreateIterator(); // 创建访问自身的一个迭代器

}

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

// 实例化的项目聚合体

Class InstanceItemAggregate : public ItemAggregate

{

CreateIterator(){ return new InstanceIterator(this); }

}

//-------------------------------------------------------------------------------------------------------



四:访问者模式Visitor:


访问者设计意图和作用是: 当我们希望对一个结构对象添加一个功能时,我们能够在不影响结构的前提下,定义一个新的对其元素的操作。(实际上,我们只是把对该元素的操作分割给每个元素自身类中实现了而已)



漸戏中适用于访问者模式的有: 任何一个比较静态的复杂结构类中都适合采用一份访问者。这里的“比较静态的复杂结构类”意思是,该结构类中元素繁多且种类复杂,且对应的操作较多,但类很少进行变化,我们就能够将,对这个结构类元素的操作独立出来,避免污染这些元素对象。

1:例如场景管理器中管理的场景节点,是非常繁多的,而且种类不一,例如有Ogre中的Root, Irrchit中就把摄象机,灯光,Mesh,公告版,声音都做为一种场景节点,每个节点类型是不同的,虽然大家都有共通的Paint(),Hide()等方法,但方法的实现形式是不同的,当我们外界调用时需要统一接口,那么我们很可能需要需要这样的代码 

Hide( Object )

{ if (Object == Mesh) HideMesh(); if (Object == Light) HideLight(); … }

此时若我们需要增加一个Object新的类型对象,我们就不得不对该函数进行修正。而我们可以这样做,让Mesh,Light他们都继承于Object,他们都实现一个函数Hide(),醣么就变成

Mesh::Hide( Visitor ) { Visitor.Hide (Mesh); }

Light::Hide(Visitor ){ Visitor.Hide (Light); }

我们在调用时只需要Object.Hide(Visitor){ return Visitor.Hide(Object); }



这样做的好处,我们免去了对重要函数的修正,Object.Hide(Visitor){}函数我们可以永久不变,但是坏处也是很明显的,因为将方法从对象集合结构中抽离出来,就意味着我们每增加一个元素,它必须继承于一个抽象的被访问者类,实现其全部函数,这个工作量很大。

所以,访问者是仅适合于一个装载不同对象的大容器,但同时又要求这个容器的元素节点不应当有大的变动时才使用。另外,废话一句,访问者破坏了OO思想的。



访问者伪代码:

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

// 访问者基类

Class Visitor

{

Virtual VisitElement( A ){ … }; // 访问的每个对象都要写这样一个方法

Virtual VisitElement( B ){ … }; 

}



// 访问者实例A

Class VisitorA

{

VisitElement( A ){ … }; // 实际的处理函数

VisitElement( B ){ … }; // 实际的处理函数

}



// 访问者实例B

Class VisitorB

{

VisitElement( A ){ … }; // 实际的处理函数

VisitElement( B ){ … }; // 实际的处理函数

}





// 被访问者基类

Class Element

{

Virtual Accept( Visitor ); // 接受访问者

}



// 被访问者实例A

Class ElementA

{

Accecpt( Visitor v ){ v-> VisitElement(this); }; // 调用注册到访问者中的处理函数

}



// 被访问者实例B

Class ElementB

{

Accecpt( Visitor v ){ v-> VisitElement(this); }; // 调用注册到访问者中的处理函数

}



//-------------------------------------------------------------------------------------------------------



五:外观模式Fa?ade


外观模式的设计意图和作用是: 将用户接触的表层和内部子集的实现分离开发。实际上,这个模式是个纸老虎,之后我们看伪代码立刻就会发现,这个模式实在用的太频繁了。



游戏中需要使用外观模式的地方是: 这个非常多了,举几个比较重要的。

1:实现平台无关性。跨平台跨库的函数调用。

2:同一个接口去读取不同的资源。

3:硬件自动识别处理系统。



外观模式伪代码

//-------------------------------------------------------------------------------------------------------

// 用户使用的接口类

Class Interface

{

// 暴露出来的函数接口函数,有且仅有一个,但内部实现是调用了两个类

Void InterfaceFun()

{
// 根据某种条件,底层自主的选择使用A或B的方法。用户无须关心底层实现

If ( XXX )

{

ActualA->Fun(); 

}

Else

{

ActualB->Fun(); 

}

}; 

}



// 实际的实现,不暴露给用户知道

Class ActualA

{

Void Fun(); 

}



// 实际的实现,不暴露给用户知道

Class ActualB

{

Void Fun(); 

}



怎么样,纸老虎吧,看起来很高深摸测的命名而已。

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



六:抽象工厂模式AbstractFactory


抽象工厂的设计意图和作用是: 封装出一个接口,这个接口负责创建一系列互相关联的对象,但用户在使用接口时不需要指定对象所在的具体的类。从中文命名也很容易明白它是进行批量生产的一个生产工厂的作用。



游戏中使用抽象工厂的地方有: 基本上任何有批量的同类形式的子件地方就会有工厂的存在。(补充一句:下面代码中的ConcreteFactory1实例工厂就是工厂,而抽象工厂仅仅是工厂的一个抽象层而已。)

1:例如,在音频方面,一个音频的抽象工厂派生出不同的工厂,有音乐工厂,音效工厂。音效工厂中又有一个创建3D音效节点的方法,一个创建普通音效节点的方法。最终用户只需要SoundFactory->Create3DNode( pFileName ); 就可以创建一个节点了。

2:场景对象。

3:渲染对象。

4:等等……

工厂与单件,管理器Manager关系一定是非常紧密的。



抽象工厂伪代码:

//-------------------------------------------------------------------------------------------------------

class AbstractProductA {}; // 抽象的产品A基类
  class AbstractProductB {}; //抽象的产品B基类



// 抽象工厂基类
  class AbstractFactory
  {
  public:
   virtual AbstractProductA* CreateProductA() = 0 ; // 创建ProductA
   virtual AbstractProductB* CreateProductB() = 0 ; // 创建ProductB
} ; 



  class ProductA1 : public AbstractProductA {}; // 产品A的实例1
  class Produ?tA2 : public AbstractProductA {}; // 产品A的实例2

  class ProductB1 : public AbstractProductB {}; // 产品B的实例1
  class ProductB2 : public AbstractProductB {}; // 产品B的实例2



// 实例工厂1

class ConcreteFactory1 : public AbstractFactory
  {
    virtual AbstractProductA* CreateProductA() { return new ProductA1() ; }
    virtual AbstractProductB* CreateProductB() { return new ProductB1() ; }
    static ConcreteFactory1* Instance() { }    // 实例工厂尽量使用单件模式
  } ; 



// 实例工厂2

class ConcreteFactory2 : public AbstractFactory
  {
    virtual Ab?tractProductA* CreateProductA() { return new ProductA2() ; }
    virtual AbstractProductB* CreateProductB() { return new ProductB2() ; }
    static ConcreteFactory2* Instance() {} // 实例工厂尽量使用单件模式
  } ; 

}

//-------------------------------------------------------------------------------------------------------

客户端代码:

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() ; 
}

//-------------------------------------------------------------------------------------------------------

分享到:
评论

相关推荐

    设计模式与游戏完美开发

    设计模式与游戏完美开发 设计模式与游戏完美开发 设计模式与游戏完美开发 设计模式与游戏完美开发 设计模式与游戏完美开发 设计模式与游戏完美开发 设计模式与游戏完美开发 设计模式与游戏完美开发 设计模式与游戏...

    P级阵地项目(设计模式与游戏完美开发)源码

    《设计模式与游戏完美开发》一书中的源码主要基于Unity3D引擎,适用于5.5及更高版本,旨在帮助开发者理解如何运用设计模式来优化游戏开发过程。在这个项目中,我们将探讨Unity3D与设计模式的结合,以及在游戏开发中...

    《设计模式与游戏完美开发》java demo.zip

    java课程设计大作业,java、算法练手项目,适合初学java、数据结构的同学拿来学习研究,基于java、GUI开发的小游戏,程序都经过测试,可以直接运行,资源含程序运行所需的源码、资源文件等全部数据,有需要的可放心...

    iOS开发常用设计模式上海UNITY3D游戏外包共2页.p

    这份"iOS开发常用设计模式上海UNITY3D游戏外包共2页.p"可能包含的内容,可能是关于如何将iOS开发中的设计模式应用到Unity3D游戏开发中的具体实践和案例。 1. **单例模式**:在iOS和Unity3D中,单例模式常用于管理...

    在游戏开发中使用设计模式(英文)

    在游戏开发中,设计模式(Design Patterns)扮演着至关重要的角色。设计模式提供了通用的解决方案,用于解决软件设计中的重复问题,它们经过了时间的考验,被广泛应用于各种软件开发领域,包括游戏开发。设计模式...

    游戏开发中的设计模式.zip

    游戏开发中的设计模式

    常用设计模式及Java程序 pdf

    本篇文章将基于“常用设计模式及Java程序”这一主题,深入探讨设计模式的基本概念、应用案例及其在Java编程中的实现。 #### 设计模式的基础 设计模式主要解决了软件开发过程中反复出现的问题。根据Christopher ...

    游戏设计模式简介

    游戏设计模式是游戏开发中的重要概念,它是一种在游戏编程中被反复使用的、已被证明有效的解决方案模板。这些模式可以帮助开发者高效地处理常见的游戏设计问题,提高代码的可重用性和可维护性。以下是对游戏设计模式...

    23种设计模式(C++).pdf

    设计模式是软件工程中的宝贵经验总结,它们为解决常见问题提供了可复用的解决方案,是提升软件可维护性和扩展性的重要工具。 1. **创建型模式**: - **工厂模式**:它提供了一种创建对象的最佳方式,通过一个公共...

    android 中常用的开发设计模式

    以下是关于"Android中常用的开发设计模式"的一些关键知识点: 1. 单例模式:保证一个类只有一个实例,提供全局访问点。在Android中,例如`Application`类或者某些全局配置对象,常常使用单例模式实现。 2. 工厂...

    研磨设计模式带书签完整版228M.7z.002

    中高级内容则深入探讨如何理解这些模式,包括模式中蕴涵什么样的设计思想,模式的本质是什么,模式如何结合实际应用,模式的优缺点以及与其他模式的关系等,以期让读者尽量去理解和掌握每个设计模式的精髓所在。...

    游戏编程模式.游戏设计与开发

    变成模式.设计与开发

    游戏设计与开发(一)

    “游戏设计与开发(一)”的学习旅程将涵盖以上各个方面,通过理论讲解和实践操作,帮助学生逐步掌握游戏开发的各个环节,为未来的专业发展奠定坚实基础。在这个过程中,不断探索、实验和创新,才能创造出真正吸引人...

    Visual C++游戏开发经典案例详解.pdf

    9. **游戏设计模式**:书中可能会讨论一些常见的游戏开发设计模式,如工厂模式、单例模式、观察者模式等,这些模式能提高代码的可读性和可维护性。 10. **调试和测试**:使用Visual Studio的调试工具进行错误排查,...

    24种设计模式以及混合设计模式

    2. 在游戏开发中,状态模式常用来管理角色的状态(如行走、攻击、防御),而装饰器模式可以用来动态添加或移除角色的能力(如增加攻击力、防御力)。 3. 在数据库连接池管理中,工厂模式用于创建连接,而单例模式...

    您的设计模式.pdf。

    在软件开发中,设计模式是一种解决特定问题的通用方法。它可以帮助开发者编写更加灵活、可维护、可扩展的代码。本书《您的设计模式》对设计模式进行了详细的讲解,涵盖了策略模式、代理模式、单例模式、多例模式、...

    Unity3D 游戏开发 PDF完整版

    Unity的组件式开发模式告别了传统纯代码开发的枯燥乏味,使得游戏开发更加灵活和高效。 本书的作者宣雨松,通过实例详细介绍了如何使用Unity进行游戏开发,尤其强调了Unity的组件式开发方法和跨平台特性。书中所...

Global site tag (gtag.js) - Google Analytics