您的位置:首页 > 其它

设计模式游戏完美开发的学习总结

2017-07-07 18:31 681 查看
一、State模式

GOF的解释”:让一个对象的行为随着内部状态的改变而变化,而该对象也像是换了类一样”。

书中用State模式实现了场景的转换。

这是State模式的结构图。



/// <summary>
2 /// 状态接口类
3 /// </summary>
4 public abstract class State {
5
6     /// <summary>
7     /// 关联的状态拥有者
8     /// </summary>
9     protected Context m_Context = null;
10
11     /// <summary>
12     /// 构造函数
13     /// </summary>
14     /// <param name="theContext">状态拥有者</param>
15     public State(Context theContext) {//构造函数接收Context 类的对象,根据这本书的绘图习惯,State 那一栏的下面会写m_Context
16         m_Context = theContext;
17     }
18
19     /// <summary>
20     /// Handle抽象方法
21     /// </summary>
22     /// <param name="Value">参数值</param>
23     public abstract void Handle(int Value);
24 }
复制代码


我在原结构图上添加了m_context,是因为这本书的后面,在一个类的构造函数里,接收另一个类的对象,然后给这个类的对象赋值,都会在其结构图上,在这个类的下面会写另外那个类的对象,这个例子中,就是m_context。

我这样区别这个问题,是因为,后面的Mediator中介者模式,也在一个接口类的构造函数里添加一个对象作为参数。在结构图上,Collegue下面有-mediator。

注意:Context 不是一个接口类,就是说,它不是一个类的集合,后面的中介者模式,Mediator是一个接口,先看看Mediator模式的结构图。



书中原图是有mediator的。

和state的结构图很像,从图上看,区别就是Mediator是作为一个接口的,即是抽象的,它有一个子类来实现它内部的功能。

Colleague类,很像State模式里的State类,从结构图的连线关系来看,State模式看起来真的是“状态模式”,State类只是作为三个子类的接口,供客户端Context在这三个子类中进行挑选,切换。这里Mediator可不是客户端,仔细看结构图,Mediator是个接口,因为它有实现它的子类。从Mediator 的结构图连线来看,它真的是“中介模式”,Mediator的子类,把其他需要沟通的类全部包含引用了,这些类的沟通都发生在Mediator的子类中。看看Mediator模式的代码:

1 //实现Colleague的类1
2 public class ConcreateColleague1 : Colleague
3 {
4     public ConcreateColleague1( Mediator theMediator) : base(theMediator)
5     {}
6
7     //执行动作
8     public void Action()
9     {
10         //执行后需要通知其他Colleague
11         m_Mediator.SendMessage(this,"Colleage1发出通知");
12     }
13
14     //Mediator通知请求
15     public override void Request(string Message)
16     {
17         Debug.Log("ConcreateColleague1.Request:"+Message);
18     }
19 }


1 //实现Colleague的类2
2 public class ConcreateColleague2 : Colleague
3 {
4     public ConcreateColleague2( Mediator theMediator) : base(theMediator)
5     {}
6
7     // 執行動作
8     public void Actio
4000
n()
9     {
10         //执行后需要通知其他Colleague
11         m_Mediator.SendMessage(this,"Colleage2发出通知");
12     }
13
14     //Mediator通知请求
15     public override void Request(string Message)
16     {
17         Debug.Log("ConcreateColleague2.Request:"+Message);
18     }
19 }


1 //实现Mediator接口,并集合管理Colleague对象
2 public class ConcreteMediator : Mediator
3 {
4     ConcreateColleague1 m_Colleague1 = null;
5     ConcreateColleague2 m_Colleague2 = null;
6
7     public void SetColleageu1( ConcreateColleague1 theColleague )
8     {
9         m_Colleague1 = theColleague;
10     }
11
12     public void SetColleageu2( ConcreateColleague2 theColleague )
13     {
14         m_Colleague2 = theColleague;
15     }
16
17     // 收到来自Colleague的通知请求
18     public override void SendMessage(Colleague theColleague,string Message)
19     {
20         // 收到Colleague1通知Colleague2
21         if( m_Colleague1 == theColleague)
22             m_Colleague2.Request( Message);
23
24         // 收到Colleague2通知Colleague1
25         if( m_Colleague2 == theColleague)
26             m_Colleague1.Request( Message);
27     }
28 }


看代码,不难发现,Colleague1和Colleague2这两个类之间并没有包含引用,它们的沟通和交流都是在ConcreteMediator 类中进行的,这里和State模式又有区别了,看看State模式的代码:

1 /// <summary>
2 /// 具体状态A
3 /// </summary>
4 public class ConcreteStateA : State {
5
6     /// <summary>
7     /// 构造函数
8     /// </summary>
9     /// <param name="theContext">状态拥有者</param>
10     public ConcreteStateA(Context theContext) : base(theContext) {
11
12     }
13
14     /// <summary>
15     /// Handle
16     /// </summary>
17     /// <param name="Value">参数值</param>
18     public override void Handle(int Value) {
19         Debug.Log("ConcreteStateA.Handle");
20         //根据条件切换到状态B
21         if(Value > 10) {
22             m_Context.SetState(new ConcreteStateB(m_Context));
23         }
24     }
25 }


4 public class ConcreteStateB:State {
5
6     /// <summary>
7     /// 构造函数
8     /// </summary>
9     /// <param name="theContext"></param>
10     public ConcreteStateB(Context theContext) : base(theContext) {
11
12     }
13
14     /// <summary>
15     /// Handle
16     /// </summary>
17     /// <param name="Value">参数值</param>
18     public override void Handle(int Value) {
19         Debug.Log("ConcreteStateB.Handle");
20         //根据条件切换到状态C
21         if(Value > 20) {
22             m_Context.SetState(new ConcreteStateC(m_Context));
23         }
24     }
25 }


public class ConcreteStateC:State {
5
6     /// <summary>
7     /// 构造函数
8     /// </summary>
9     /// <param name="theContext"></param>
10     public ConcreteStateC(Context theContext) : base(theContext) {
11
12     }
13
14     /// <summary>
15     /// Handle
16     /// </summary>
17     /// <param name="Value">参数值</param>
18     public override void Handle(int Value) {
19         Debug.Log("ConcreteStateC.Handle");
20         //根据条件切换到状态A
21         if(Value > 30) {
22             m_Context.SetState(new ConcreteStateA(m_Context));
23         }
24     }
25 }


这里的区别也是由每个模式的特点来决定的,在State模式里,客户端的方法和操作,贯穿着State类的三个子类,m_Context.SetState();让我们感受下。。。。。。这好像是线性贯穿的。

我好像感受到什么了,一个东西,或者叫object,对外要呈现不同的状态,它要贯穿游走在这几个状态,线性贯穿有木有,可以用状态模式来设计。

Mediator 中介者模式,比较好理解,把需要沟通的类,用Mediator 接口的子类(实现类)全部包含,让它们在里面沟通,它们自己的类里并不互相包含引用。而Mediator的对象是在这些需要沟通的子类的接口类在构造函数里就生成赋值的,也就是说,Mediator的对象也是贯穿在这些个需要沟通的子类里的,中介者嘛,必须和每个需要沟通的类打交道。

总结下,贯穿,游离,沟通,切换,有这些动作的对象,都会在它要植入的对象的类的构造函数中进行生成和引用。

再来看看桥接模式,我先画个结构图:



左边的两个方框代表两个类,右面的带圆角的方框代表另外的四个类,左边的两个类都要用到右边那四个类的方法,就是说,左边的都要和右边的进行连线,左边和右边的那一列彼此不连线。这样的连线方式,就可以用桥接模式。

把左右两列的类分别抽象化成两个接口,比如玩家类这个接口,有敌人类和士兵类,炸弹,枪,火箭筒各类武器抽象成一个武器类

1 /// <summary>
2 /// 武器类群组(武器接口)
3 /// </summary>
4 public abstract class IWeapon {
5
6     /// <summary>
7     /// 武器的拥有者
8     /// </summary>
9     protected ICharacter m_WeaponOwner = null;
10
11     /// <summary>
12     /// 攻击目标
13     /// </summary>
14     public abstract void Fire(ICharacter
a941
theTarget);
15
16     /// <summary>
17     /// 显示射击特效
18     /// </summary>
19     protected void ShowShootEffect() {
20
21     }
22
23     /// <summary>
24     /// 显示子弹特效
25     /// </summary>
26     protected void ShowBulletEffect(Vector3 TargetPosition,float LineWidth,float DisplayTime) {
27
28     }
29
30     /// <summary>
31     /// 播放音效
32     /// </summary>
33     protected void ShowSoundEffect(string ClipName) {
34
35     }
36 }


1 /// <summary>
2 /// 角色接口
3 /// </summary>
4 public abstract class ICharacter {
5     ...
6     /// <summary>
7     /// 使用的武器
8     /// </summary>
9     private IWeapon m_Weapon = null;
10
11     protected void WeaponAttackTarget(ICharacter Target) {
12         m_Weapon.Fire(Target);
13     }
14
15     /// <summary>
16     /// 攻击目标
17     /// </summary>
18     public abstract void Attack(ICharacter Target);
19
20     /// <summary>
21     /// 被其他角色攻击
22     /// </summary>
23     public abstract void UnderAttack(ICharacter Attacker);
24     ...
25 }


和state模式,中介者模式不同,桥接模式,武器和玩家这两个接口之间互相包含引用,彼此的构造函数并没有带对方接口类的对象作为参数。这是我看出来状态模式,中介者模式,桥接模式之间的区别。

再总结下:

State模式,一个客户端,多个状态类,把状态类抽象化成一个接口,供客户端进行调用,此时,状态的接口在其构造函数内,要把客户端的对象作为参数,并对客户端对象进行赋值。而多个状态类的内部有实现状态切换的方法,供客户端进行调用。

中介者模式,把需要沟通的多个对象抽象成一个接口,中介者也是一个需要实现的接口类,中介者在多个需要沟通的对象实例化时就生成,就是说,多个对象的接口的构造函数是以中介者类为参数的,然后给中介者对象赋值。在中介者的实现类内部,包含所有需要沟通的类,在中介者的实现类内部,让这些需要沟通的类自己们互相交流。

桥接模式,最简单,抽象出两个大接口,比如图形渲染器例子,在一个接口里只有一个绘制图形方法,在需要调用绘制方法的类里定义一个set方法,设置使用哪一个绘制引擎进行绘制。

策略模式,比较像桥接模式,只不过策略模式是客户端根据需求来调用不同的方法。



桥接模式Context那一栏里是个抽象接口。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  设计模式