组合模式介绍
- 定义
将对象组合成树形结构以表示“部分-整体”的层次结构,
使得用户对单个对象和组合对象的使用具有一致性。
组合模式
- Component 组件(DrawingElement)
在组合中声明对象的接口。
为所有类的公共接口实现默认行为,视情况而定。
声明一个用于访问和管理其子组件的接口。
(可选)定义了一个接口,用于在递归结构中访问组件的父组件,并在合适的情况下实现它。
- Leaf 叶(PrimitiveElement)
表示合成中的叶子对象。 一片叶子没有孩子。
为组合中的原始对象定义行为。
- Composite 复合(CompositeElement)
定义有子组件的行为。
存储子组件。
在组件接口中实现子操作。
- Client 客户机(CompositeApp)
通过Component接口操作组合中的对象。
using System;
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class CompositeStructure : MonoBehaviour
{
void Start ( )
{
// Create a tree structure
Composite root = new Composite("root");
root.Add(new Leaf("Leaf A"));
root.Add(new Leaf("Leaf B"));
Composite comp = new Composite("Composite X");
comp.Add(new Leaf("Leaf XA"));
comp.Add(new Leaf("Leaf XB"));
root.Add(comp);
root.Add(new Leaf("Leaf C"));
// Add and remove a leaf
Leaf leaf = new Leaf("Leaf D");
root.Add(leaf);
root.Remove(leaf);
// Recursively display tree
root.Display(1);
}
}
/// <summary>
/// The 'Component' abstract class
/// </summary>
abstract class Component
{
protected string name;
// Constructor
public Component(string name)
{
this.name = name;
}
public abstract void Add(Component c);
public abstract void Remove(Component c);
public abstract void Display(int depth);
}
/// <summary>
/// The 'Composite' class
/// </summary>
class Composite : Component
{
private List<Component> _children = new List<Component>();
// Constructor
public Composite(string name)
: base(name)
{
}
public override void Add(Component component)
{
_children.Add(component);
}
public override void Remove(Component component)
{
_children.Remove(component);
}
public override void Display(int depth)
{
Debug.Log(new String('-', depth) + name);
// Recursively display child nodes
foreach (Component component in _children)
{
component.Display(depth + 2);
}
}
}
/// <summary>
/// The 'Leaf' class
/// </summary>
class Leaf : Component
{
// Constructor
public Leaf(string name)
: base(name)
{
}
public override void Add(Component c)
{
Debug.Log("Cannot add to a leaf");
}
public override void Remove(Component c)
{
Debug.Log("Cannot remove from a leaf");
}
public override void Display(int depth)
{
Debug.Log(new String('-', depth) + name);
}
}
组合模式案例1
using System;
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
//这个真实世界的代码演示了Composite模式,
//用于构建一个由原始节点(线、圆等)和Composite组成的
//图形树结构节点(组成更复杂元素的绘图元素组)。
namespace CompositePatternExample1
{
public class CompositePatternExample1 : MonoBehaviour
{
void Start()
{
// Create a tree structure
CompositeElement root =
new CompositeElement("Picture");
root.Add(new PrimitiveElement("Red Line"));
root.Add(new PrimitiveElement("Blue Circle"));
root.Add(new PrimitiveElement("Green Box"));
// Create a branch
CompositeElement comp =
new CompositeElement("Two Circles");
comp.Add(new PrimitiveElement("Black Circle"));
comp.Add(new PrimitiveElement("White Circle"));
root.Add(comp);
// Add and remove a PrimitiveElement
PrimitiveElement pe =
new PrimitiveElement("Yellow Line");
root.Add(pe);
root.Remove(pe);
// Recursively display nodes
root.Display(1);
}
}
/// <summary>
/// The 'Component' Treenode
/// </summary>
abstract class DrawingElement
{
protected string _name;
// Constructor
public DrawingElement(string name)
{
this._name = name;
}
public abstract void Add(DrawingElement d);
public abstract void Remove(DrawingElement d);
public abstract void Display(int indent);
}
/// <summary>
/// The 'Leaf' class
/// </summary>
class PrimitiveElement : DrawingElement
{
// Constructor
public PrimitiveElement(string name)
: base(name)
{
}
public override void Add(DrawingElement c)
{
Debug.Log("Cannot add to a PrimitiveElement");
}
public override void Remove(DrawingElement c)
{
Debug.Log("Cannot remove from a PrimitiveElement");
}
public override void Display(int indent)
{
Debug.Log(new String('-', indent) + " " + _name);
}
}
/// <summary>
/// The 'Composite' class
/// </summary>
class CompositeElement : DrawingElement
{
private List<DrawingElement> elements =
new List<DrawingElement>();
// Constructor
public CompositeElement(string name)
: base(name)
{
}
public override void Add(DrawingElement d)
{
elements.Add(d);
}
public override void Remove(DrawingElement d)
{
elements.Remove(d);
}
public override void Display(int indent)
{
Debug.Log(new String('-', indent) +
"+ " + _name);
// Display each child element on this node
foreach (DrawingElement d in elements)
{
d.Display(indent + 2);
}
}
}
}
组合模式案例2
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
namespace CompositePatternExample2
{
public class CompositePatternExample2 : MonoBehaviour
{
void Start()
{
SongComponent industrialMusic = new SongGroup("Industrial Music", "Industrial music is a genre of experimental music that draws on transgressive and provocative themes. The term was coined in the mid-1970s with the founding of Industrial Records by Genesis P-Orridge of Throbbing Gristle and Monte Cazazza; on Throbbing Gristle's debut album The Second Annual Report, they coined the slogan \"industrial music for industrial people\".");
SongComponent heavyMetalMusic = new SongGroup("Heavy Metal Music", "Heavy metal is a genre of rock music[1] that developed in the late 1960s and early 1970s, largely in the United States and the United Kingdom.[2] With roots in blues rock and psychedelic rock,[3] the bands that created heavy metal developed a thick, massive sound, characterized by highly amplified distortion, extended guitar solos, emphatic beats, and overall loudness. Heavy metal lyrics and performance styles are often associated with masculinity, aggression, and machismo.[3]");
SongComponent dubstepMusic = new SongGroup("Dubstep Music", "Dubstep /ˈdʌbstɛp/ is a genre of electronic dance music that originated in South London, England. It emerged in the late 1990s as a development within a lineage of related styles such as 2-step garage, broken beat, drum and bass, jungle, dub and reggae.[2] In the UK the origins of the genre can be traced back to the growth of the Jamaican sound system party scene in the early 1980s.[2][3] The music generally features syncopated drum and percussion patterns with bass lines that contain prominent sub bass frequencies.");
SongComponent everySong = new SongGroup("Song List", "Every Song available");
everySong.Add(industrialMusic);
industrialMusic.Add(new Song("Head Like a Hole", "NIN", 1990));
industrialMusic.Add(new Song("headhunter", "front 242", 1988));
// see: here we are adding a group into a group and build up the hierarchy!!!!
industrialMusic.Add(dubstepMusic);
dubstepMusic.Add(new Song("Centipede", "Knife Party", 2012));
dubstepMusic.Add(new Song("Tetris", "doctor P", 2011));
everySong.Add(heavyMetalMusic);
heavyMetalMusic.Add(new Song("War Pigs", "Black Sabath", 1970));
heavyMetalMusic.Add(new Song("Ace of spades", "Motorhead", 1980));
DiscJockey crazyLarry = new DiscJockey(everySong);
crazyLarry.GetSongList();
}
}
public abstract class SongComponent
{
public virtual void Add(SongComponent component) { }
public virtual void Remove(SongComponent component) { }
public virtual SongComponent Get(int index) { return null; }
public abstract void DisplaySongInformation();
}
public class SongGroup : SongComponent
{
protected List<SongComponent> components = new List<SongComponent>();
public string groupName { get; protected set; }
public string groupDescription { get; protected set; }
public SongGroup(string name, string description)
{
this.groupName = name;
this.groupDescription = description;
}
public override void Add(SongComponent component)
{
components.Add(component);
}
public override void Remove(SongComponent component)
{
components.Remove(component);
}
public override SongComponent Get(int i)
{
return components[i];
}
public override void DisplaySongInformation()
{
Debug.Log(groupName + " - " + groupDescription);
// now iterate through all groups inside this group
IEnumerator iterator = components.GetEnumerator();
while (iterator.MoveNext())
{
SongComponent songComponent = (SongComponent)iterator.Current;
songComponent.DisplaySongInformation();
}
}
}
public class Song : SongComponent
{
public string songName { get; protected set; }
public string bandName { get; protected set; }
public int releaseYear { get; protected set; }
public Song(string name, string band, int year)
{
this.songName = name;
this.bandName = band;
this.releaseYear = year;
}
public override void DisplaySongInformation()
{
Debug.Log("Song of " + songName + " - " + bandName + " : " + releaseYear);
}
}
public class DiscJockey
{
protected SongComponent songList;
public DiscJockey(SongComponent songList)
{
this.songList = songList;
}
public void GetSongList()
{
songList.DisplaySongInformation();
}
}
}