一、策略模式(Unity3d演示)

来源:互联网 发布:丹麦语翻译软件 编辑:程序博客网 时间:2024/06/09 17:56

转自:http://blog.csdn.net/wowkk/article/details/9865855  

先学设计模式还是先学数据结构或算法?我还是选择前者。兴趣在应用层呵呵。

    不久前我还以为三层架构也是设计模式中的一种,现在才知道,开发模式和设计模式是不一样的。

    就我目前接触过的项目,基本都采用简单三层架构,最多加上工厂模式。感觉三层架构就像是“万金油”,哪里都能运用上,那为什么还要用到设计模式呢~我知道这肯是因为我碰到的场景不多。为了多点设计想法、多点学习英语,《head+first+设计模式》中英文一起看!

 
    策略模式(The Strategy pattern)
    设计模式中的策略模式是什么?要怎样应用策略模式?看看我的理解对不对吧^_^Unity3d游戏引擎演示。
    前半部分对策略模式的理解需要一些多态基础。后部分的演示需要Unity3d基础(写了一些关于Unity3d的教程了,以后成熟了再发吧。)
   
    定义:定义算法族,分别封装起来,让它们之前可以互相替换,此模式让算法的变化独立于使用算法的客户。
    场景:有一个游戏,游戏里有一个池塘,池塘里有一堆鸭子。有各种各样的鸭子,它们都继承自同一个基类,各自重写了基类的一些功能。以前,鸭子都会游,不同鸭子会有不同的叫声(多态Polymorphism)。现在,突然要给一些鸭子添加“飞”的功能。如果像以前那样,在基类实现“飞”的功能,那所有鸭子都会飞了。如果给不要飞的鸭子重写“飞”的函数让它不会飞或者只给要飞的鸭子写“飞”的功能,那将丢失代码的可重用性(Reuse)。

    策略模式将对象模型(Model)与对象的一些经常变动的行为(Behaviour)进行分离,将原有的“Is-A”(是一个类)模式改为“Has-A”(类包含类)模式。

    行为类,比如飞,也有一个共同接口(Interface)(相当于纯虚类?)。需要的话,可以多态成多种多样的飞行类。

    在对象模型里,比如鸭子。封装(Encapsulation)了一个飞行接口,然后在构造函数里,对这个接口进行实例化(Instantiase),让鸭子具有某种飞的功能。之后,给鸭子一个飞的方法,调用接口飞的行为,让鸭子飞起来。

    这样,我们在应用层中,实例化一个鸭子模型,需要飞时,直接使用该模型的飞方法即可。

    这是策略模式一个强大的优点。相对于普通的面向对象设计(Object - Oriented),大大提高代码的可重用性。

    另外一个优点,就是可以在程序运行时,改变对象模型的行为。只需要给模型写一个 setBehavior(NewBehavior n){替换将私有的行为变量;}方法,这样,就算新设计的飞行行为,也可以很迅速的分配给任何模型。

    下面试下能否利用unity3d来演示。(在我的理解中,其实游戏引擎已经完全做到了这一点!导入一个模型,里面的“动画组件”就是行为分离。需要让模型进行某些动作,只需要在“动画组件”里进行设计,然后赋给模型即可!)

    我专门找了一个鸭子模型:
    
    为了测试方便,就不使用鸭子模型继承了。
    首先创建一个飞行接口:
[csharp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. public interface IFly  
  2.   
  3.      {  
  4.   
  5.         void Fly(GameObject g); //GameObject参数指的是“鸭子”  
  6.   
  7.      }  

   
    以后新添加的飞行类型都继承自该接口。比如这里的“垂直上飞”行为
   
[csharp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. public class Fly1:IFly  
  2.   
  3.      {  
  4.   
  5.         //让物体垂直向上飞  
  6.   
  7.         void IFly.Fly(GameObject g) {  
  8.   
  9.             g.transform.Translate(0, 1 * Time.deltaTime, 0, Space.Self);  
  10.   
  11.         }  
  12.   
  13.      }  

 

[csharp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. public class Fly2:IFly  
  2. {  
  3.        //45度向前飞行  
  4.        void IFly.Fly(GameObject g) {  
  5.            g.transform.Translate(1 * Time.deltaTime, 1 * Time.deltaTime, 0, Space.Self);  
  6.        }  
  7. }  


 


    接着就是创建一个鸭子类了。
[csharp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. public class Duck {  
  2.   
  3.     private GameObject duck;//鸭子模型(在构造函数中赋值)  
  4.   
  5.     private IFly fly;//鸭子该如何飞?(在构造函数中初始化,或者在SetFlyBehavior()函数中设置)  
  6.   
  7.     public Duck(GameObject g)  
  8.   
  9.     {  
  10.   
  11.         duck = g;  
  12.   
  13.         fly = new Fly1();//多态的精髓!      
  14. }  
  15.   
  16.     //让鸭子飞  
  17.   
  18.     public void Fly()  
  19.   
  20.     {  
  21.   
  22.         fly.Fly(duck);  
  23.   
  24.     }  
  25.   
  26.     //设置鸭子飞的方式  
  27.   
  28.     public void SetFlyBehavior(IFly f) {  
  29.   
  30.         fly = f;     
  31.   
  32.     }  
  33.   
  34. }  

    最后一个“类”,用来控制鸭子的。
   
[csharp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. public class Control : MonoBehaviour {  
  2.   
  3.     public GameObject g;  
  4.   
  5.     private Duck d;  
  6.   
  7.      // Use this for initialization  
  8.   
  9.      void Start () {  
  10.   
  11.         d = new Duck(g);  
  12.   
  13.      }  
  14.   
  15.       
  16.   
  17.      // Update is called once per frame  
  18.   
  19.      void Update () {  
  20.   
  21.         //按W键时飞行  
  22.   
  23.         if (Input.GetKey(KeyCode.W)) {  
  24.   
  25.             d.Fly();  
  26.   
  27.         }  
  28.   
  29.         //按空格键时改变飞行行为  
  30.   
  31.         if (Input.GetKey(KeyCode.Space)) {  
  32.   
  33.             d.SetFlyBehavior(new Fly2());  
  34.   
  35.         }  
  36.   
  37.      }  
  38.   
  39. }  


    最后!把“控制类”扔给相机,然后把“鸭子模型”扔给“控制类”的GameObject g变量!搞定!
    CSDN博客不能传视频,就录制下GIF凑合下吧。(飞到中间的时候,我按了空格键,然后就改变的飞行方式)
0 0
原创粉丝点击