先简单了解一下适配器模式。
适配器模式
适配器模式通过将类自己的接口包裹在一个已存在的类中使得因接口不兼容而不能在一起工作的类能在一起工作,有两种类型的适配器模式:
对象适配器模式
在这种适配器模式中,适配器容纳一个它包裹的类的实例。在这种情况下,适配器调用被包裹对象的物理实体。
类适配器模式
这种适配器模式下,适配器继承自已实现的类(一般多重继承)。
描述
按adapter模式魔改飞碟(Disk)基础版(仅使用射线,动作管理),使它同时支持物理运动与运动学(变换)运动
设计
对动作管理运用类适配器模式,设计运动学适配器CCActionManager和物理运动适配器PhysiscActionManager,PhysiscActionManager与CCActionManager的不同仅仅在于将Update改成FixedUpdate。
适配器模式的多态的设计要用到接口。这两个适配器实现了同一接口ActionManager。
ActionManager提供了一个简单动作方法,用于执行抛出飞碟的动作。
ActionManager
public interface ActionManager{
void singleRunAction (GameObject gameObject, int speedLevel);
}
由于PhysiscActionManager要用到FixedUpdate方法,所以要对SSAction(作用)、SSActionManager(作用)添加FixedUpdate,方法与Update相同,除了把其中包含的Update换成FixedUpdate。
SSAction
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public enum SSActionEventType : int { Started, Competeted }
public interface ISSActionCallback {
void SSActionEvent(SSAction source, SSActionEventType events = SSActionEventType.Competeted,
int intParam = 0, string strParam = null, Object objectParam = null);
}
public class SSAction : ScriptableObject {
public bool enable = true;
public bool destroy = false;
public GameObject gameobject { get; set; }
public Transform transform { get; set; }
public ISSActionCallback callback{ get; set; }
protected SSAction () {}
//Use this for initialization
public virtual void Start () {
throw new System.NotImplementedException ();
}
// Update is called once per frame
public virtual void Update () {
throw new System.NotImplementedException ();
}
// FixedUpdate
public virtual void FixedUpdate () {
throw new System.NotImplementedException ();
}
}
SSActionManager
public class SSActionManager : MonoBehaviour
{
private Dictionary<int, SSAction> actions = new Dictionary<int, SSAction>();
private List<SSAction> waitingAdd = new List<SSAction>();
private List<int> waitingDelete = new List<int>();
// Use this for initialization
void Start() {
}
// Update is called once per frame
protected void Update() {
foreach (SSAction ac in waitingAdd) actions[ac.GetInstanceID()] = ac;
waitingAdd.Clear();
foreach (KeyValuePair<int, SSAction> kv in actions) {
SSAction ac = kv.Value;
if (ac.destroy)
waitingDelete.Add(ac.GetInstanceID());
else if (ac.enable)
ac.Update();
}
foreach (int key in waitingDelete) {
SSAction ac = actions [key];
actions.Remove (key);
DestroyObject (ac);
}
waitingDelete.Clear();
}
// FixedUpdate
protected void FixedUpdate() {
foreach (SSAction ac in waitingAdd) actions[ac.GetInstanceID()] = ac;
waitingAdd.Clear();
foreach (KeyValuePair<int, SSAction> kv in actions) {
SSAction ac = kv.Value;
if (ac.destroy)
waitingDelete.Add(ac.GetInstanceID());
else if (ac.enable)
ac.FixedUpdate();
}
foreach (int key in waitingDelete) {
SSAction ac = actions [key];
actions.Remove (key);
DestroyObject (ac);
}
waitingDelete.Clear();
}
public void RunAction(GameObject gameobject, SSAction action, ISSActionCallback manager) {
action.gameobject = gameobject;
action.transform = gameobject.transform;
action.callback = manager;
waitingAdd.Add(action);
action.Start();
}
}
在写继承时要注意C#的一个语法规定,继承的父类SSActionManager要写在最前面,后面跟着实现的接口,因为C#只支持单继承,但可以实现多个接口。
CCActionManager
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CCActionManager : SSActionManager, ActionManager, ISSActionCallback {
public DiskFactory diskFactory;
void Start() {
diskFactory = DiskFactory.getInstance();
}
public new void Update() {
base.Update ();
}
public new void FixedUpdate() {
}
public void singleRunAction(GameObject gameObject, int speedLevel) {
this.RunAction (gameObject, FlyDisk.GetSSAction (speedLevel), this);
}
#region ISSActionCallback implementation
public void SSActionEvent(SSAction source, SSActionEventType events = SSActionEventType.Competeted,
int intParam = 0, string strParam = null, Object objectParam = null){
}
#endregion
}
PhysiscActionManager
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PhysicsActionManager : SSActionManager, ActionManager, ISSActionCallback {
public DiskFactory diskFactory;
void Start() {
diskFactory = DiskFactory.getInstance();
}
public new void Update() {
}
public new void FixedUpdate() {
base.FixedUpdate ();
}
public void singleRunAction (GameObject gameObject, int speedLevel) {
this.RunAction (gameObject, FlyDisk.GetSSAction (speedLevel), this);
}
#region ISSActionCallback implementation
public void SSActionEvent(SSAction source, SSActionEventType events = SSActionEventType.Competeted,
int intParam = 0, string strParam = null, Object objectParam = null){
}
#endregion
}