组合模式
将对象以树状结构组合,用以表现部分-全体的层次关系。组合模式让客户端在操作各个对象或组合对象时是一致的。
组合模式的定义
参与者说明如下:
- Component(组件界面)
- 定义树状结构中,每一个节点可以使用的操作方法。
- Composite(组合节点)
- 即根节点的盖帘
- 会包含叶节点的对象
- 会实现Component(组件界面)中与子节点操作有关的方法,如Add、Remove、GetChild等
- Leaf(叶节点)
- 不在包含任何子节点的最终节点
- 实现Component(组件界面)中基本的行为,对于与子节点操作有关的方法可以不实现,也可以提出警告或 弹出例外。
具体实现
// 複合體內含物件之介面
public abstract class IComponent
{
protected string m_Value;
public abstract void Operation(); // 一般操作
// 加入節點
public virtual void Add(IComponent theComponent)
{
Debug.LogWarning("子類別沒實作");
}
// 移除節點
public virtual void Remove(IComponent theComponent)
{
Debug.LogWarning("子類別沒實作");
}
// 取得子節點
public virtual IComponent GetChild(int Index)
{
Debug.LogWarning("子類別沒實作");
return null;
}
}
// 代表複合結構之終端物件
public class Leaf : IComponent
{
public Leaf(string Value)
{
m_Value = Value;
}
public override void Operation()
{
Debug.Log("Leaf[" + m_Value + "]執行Operation()");
}
}
// 代表複合結構的節點之行為
public class Composite : IComponent
{
List<IComponent> m_Childs = new List<IComponent>();
public Composite(string Value)
{
m_Value = Value;
}
// 一般操作
public override void Operation()
{
Debug.Log("Composite[" + m_Value + "]");
foreach (IComponent theComponent in m_Childs)
theComponent.Operation();
}
// 加入節點
public override void Add(IComponent theComponent)
{
m_Childs.Add(theComponent);
}
// 移除節點
public override void Remove(IComponent theComponent)
{
m_Childs.Remove(theComponent);
}
// 取得子節點
public override IComponent GetChild(int Index)
{
return m_Childs[Index];
}
}
用组合模式实现用户界面
使用工具树状查找UI组件或对象
public static class UITool
{
private static GameObject m_CanvasObj = null; // 場景上的2D畫布物件
public static void ReleaseCanvas()
{
m_CanvasObj = null;
}
// 找尋限定在Canvas畫布下的UI界面
public static GameObject FindUIGameObject(string UIName)
{
if(m_CanvasObj == null)
m_CanvasObj = UnityTool.FindGameObject( "Canvas" );
if(m_CanvasObj ==null)
return null;
return UnityTool.FindChildGameObject( m_CanvasObj, UIName);
}
// 取得UI元件
public static T GetUIComponent<T>(GameObject Container,string UIName) where T : UnityEngine.Component
{
// 找出子物件
GameObject ChildGameObject = UnityTool.FindChildGameObject( Container, UIName);
if( ChildGameObject == null)
return null;
T tempObj = ChildGameObject.GetComponent<T>();
if( tempObj == null)
{
Debug.LogWarning("元件["+UIName+"]不是["+ typeof(T) +"]");
return null;
}
return tempObj;
}
public static Button GetButton(string BtnName)
{
// 取得Canvas
GameObject UIRoot = GameObject.Find("Canvas");
if(UIRoot==null)
{
Debug.LogWarning("場景上沒有UI Canvas");
return null;
}
// 找出對應的Button
Transform[] allChildren = UIRoot.GetComponentsInChildren<Transform>();
foreach(Transform child in allChildren)
{
if( child.name == BtnName )
{
Button tmpBtn = child.gameObject.GetComponent<Button>();
if(tmpBtn == null)
Debug.LogWarning("UI原件["+BtnName+"]不是Button");
return tmpBtn;
}
}
Debug.LogWarning("UI Canvas中沒有Button["+BtnName+"]存在");
return null;
}
// 取得UI元件
public static T GetUIComponent<T>(string UIName) where T : UnityEngine.Component
{
// 取得Canvas
GameObject UIRoot = GameObject.Find("Canvas");
if(UIRoot==null)
{
Debug.LogWarning("場景上沒有UI Canvas");
return null;
}
return GetUIComponent<T>( UIRoot,UIName);
}
}
组合模式的优缺点
优点:
- 界面与功能分离
- 工作切分更容易
- 界面更改不影响项目
缺点
- 组件名称重复
- 组件更名不易