1.单例模式
概念很简单,保证一个类仅有一个实例,并提供一个访问它的全局访问点。
//单例模式
static GameController _instance;
void Awake()
{
_instance = this;
}
public static GameController Instance
{
get
{
// 不需要再检查变量是否为null
return _instance;
}
}
2.观察者模式
概念:它将对象与对象之间创建一种依赖关系,当其中一个对象发生变化时,它会将这个变化通知给与其创建关系的对象中,实现自动化的通知更新。
代码实现
/// <summary>
/// 抽象观察者
/// </summary>
public interface ISubject //接口
{
void Notify();
}
/// <summary>
/// 工作岗位,作为这里的观察者的抽象
/// </summary>
public abstract class JobStation //抽象类
{
public abstract void Update();
}
/// <summary>
/// 具体主题,这里是客户
/// </summary>
public class Customer : ISubject
{
private string customerState;
private IList<JobStation> observers = new List<JobStation>();
/// <summary>
/// 增加观察者
/// </summary>
/// <param name="observer"></param>
public void Attach(JobStation observer)
{
this.observers.Add(observer);
}
/// <summary>
/// 移除观察者
/// </summary>
/// <param name="observer"></param>
public void Detach(JobStation observer)
{
this.observers.Remove(observer);
}
/// <summary>
/// 客户状态
/// </summary>
public string CustomerState
{
get { return customerState; }
set { customerState = value; }
}
public void Notify()
{
foreach (JobStation o in observers)
{
o.Update();
}
}
}
/// <summary>
/// 会计
/// </summary>
public class Accountant : JobStation
{
private string accountantState;
private Customer customer;
public Accountant(Customer customer)
{
this.customer = customer;
}
/// <summary>
/// 更新状态
/// </summary>
public override void Update()
{
if (customer.CustomerState == "已付款")
{
Console.WriteLine("我是会计,我来开具发票。");
accountantState = "已开发票";
}
}
}
/// <summary>
/// 出纳
/// </summary>
public class Cashier : JobStation
{
private string cashierState;
private Customer customer;
public Cashier(Customer customer)
{
this.customer = customer;
}
public override void Update()
{
if (customer.CustomerState == "已付款")
{
Console.WriteLine("我是出纳员,我给登记入账。");
cashierState = "已入账";
}
}
}
/// <summary>
/// 配送员
/// </summary>
public class Dilliveryman : JobStation
{
private string dillivierymanState;
private Customer customer;
public Dilliveryman(Customer customer)
{
this.customer = customer;
}
public override void Update()
{
if (customer.CustomerState == "已付款")
{
Console.WriteLine("我是配送员,我来发货。");
dillivierymanState = "已发货";
}
}
}
客户端代码
class Program
{
static void Main(string[] args)
{
Customer subject = new Customer();
subject.Attach(new Accountant(subject));
subject.Attach(new Cashier(subject));
subject.Attach(new Dilliveryman(subject));
subject.CustomerState = "已付款";
subject.Notify();
Console.Read();
}
}
运行结果:
我是会计,我来开具发票。
我是出纳员,我给登记入账。
我是配送员,我来发货。
优点
观察者模式解除了主题和具体观察者的耦合,让耦合的双方都依赖于抽象,而不是依赖具体。从而使得各自的变化都不会影响另一边的变化。
缺点
依赖关系并未完全解除,抽象通知者依旧依赖抽象的观察者。
适用场景
当一个对象的改变需要通知其它对象时,而且它不知道具体有多少个对象有待改变时。
一个抽象某型有两个方面,当其中一个方面依赖于另一个方面,这时用观察者模式可以将这两者封装在独立的对象中使它们各自独立地改变和复用。
3.迭代器模式
迭代器模式提供了一种方法顺序访问一个聚合对象(理解为集合对象)中各个元素,而又无需暴露该对象的内部表示,这样既可以做到不暴露集合的内部结构,又可让外部代码透明地访问集合内部的数据。
// 抽象聚合类
public interface IListCollection
{
Iterator GetIterator();
}
// 迭代器抽象类
public interface Iterator
{
bool MoveNext();
Object GetCurrent();
void Next();
void Reset();
}
// 具体聚合类
public class ConcreteList : IListCollection
{
int[] collection;
public ConcreteList()
{
collection = new int[] { 2, 4, 6, 8 };
}
public Iterator GetIterator()
{
return new ConcreteIterator(this);
}
public int Length
{
get { return collection.Length; }
}
public int GetElement(int index)
{
return collection[index];
}
}
// 具体迭代器类
public class ConcreteIterator : Iterator
{
// 迭代器要集合对象进行遍历操作,自然就需要引用集合对象
private ConcreteList _list;
private int _index;
public ConcreteIterator(ConcreteList list)
{
_list = list;
_index = 0;
}
public bool MoveNext()
{
if (_index < _list.Length)
{
return true;
}
return false;
}
public Object GetCurrent()
{
return _list.GetElement(_index);
}
public void Reset()
{
_index = 0;
}
public void Next()
{
if (_index < _list.Length)
{
_index++;
}
}
}
// 客户端
class Program
{
static void Main(string[] args)
{
Iterator iterator;
IListCollection list = new ConcreteList();
iterator = list.GetIterator();
while (iterator.MoveNext())
{
int i = (int)iterator.GetCurrent();
Console.WriteLine(i.ToString());
iterator.Next();
}
Console.Read();
}
}
迭代器模式的适用场景
- 系统需要访问一个聚合对象的内容而无需暴露它的内部表示。
- 系统需要支持对聚合对象的多种遍历。
- 系统需要为不同的聚合结构提供一个统一的接口。
迭代器模式的优缺点
优点:
- 迭代器模式使得访问一个聚合对象的内容而无需暴露它的内部表示,即迭代抽象。
- 迭代器模式为遍历不同的集合结构提供了一个统一的接口,从而支持同样的算法在不同的集合结构上进行操作
迭代器模式存在的缺陷:
- 迭代器模式在遍历的同时更改迭代器所在的集合结构会导致出现异常。所以使用foreach语句只能在对集合进行遍历,不能在遍历的同时更改集合中的元素。
4.访问者模式的定义
访问者模式是封装一些施加于某种数据结构之上的操作。一旦这些操作需要修改的话,接受这个操作的数据结构则可以保存不变。访问者模式适用于数据结构相对稳定的系统, 它把数据结构和作用于数据结构之上的操作之间的耦合度降低,使得操作集合可以相对自由地改变。
数据结构的每一个节点都可以接受一个访问者的调用,此节点向访问者对象传入节点对象,而访问者对象则反过来执行节点对象的操作。这样的过程叫做“双重分派”。节点调用访问者,将它自己传入,访问者则将某算法针对此节点执行。
namespace VistorPattern
{
// 抽象元素角色
public abstract class Element
{
public abstract void Accept(IVistor vistor);
public abstract void Print();
}
// 具体元素A
public class ElementA :Element
{
public override void Accept(IVistor vistor)
{
// 调用访问者visit方法
vistor.Visit(this);
}
public override void Print()
{
Console.WriteLine("我是元素A");
}
}
// 具体元素B
public class ElementB :Element
{
public override void Accept(IVistor vistor)
{
vistor.Visit(this);
}
public override void Print()
{
Console.WriteLine("我是元素B");
}
}
// 抽象访问者
public interface IVistor
{
void Visit(ElementA a);
void Visit(ElementB b);
}
// 具体访问者
public class ConcreteVistor :IVistor
{
// visit方法而是再去调用元素的Accept方法
public void Visit(ElementA a)
{
a.Print();
}
public void Visit(ElementB b)
{
b.Print();
}
}
// 对象结构
public class ObjectStructure
{
private ArrayList elements = new ArrayList();
public ArrayList Elements
{
get { return elements; }
}
public ObjectStructure()
{
Random ran = new Random();
for (int i = 0; i < 6; i++)
{
int ranNum = ran.Next(10);
if (ranNum > 5)
{
elements.Add(new ElementA());
}
else
{
elements.Add(new ElementB());
}
}
}
}
class Program
{
static void Main(string[] args)
{
ObjectStructure objectStructure = new ObjectStructure();
foreach (Element e in objectStructure.Elements)
{
// 每个元素接受访问者访问
e.Accept(new ConcreteVistor());
}
Console.Read();
}
}
}
访问者模式的应用场景
- 如果系统有比较稳定的数据结构,而又有易于变化的算法时,此时可以考虑使用访问者模式。因为访问者模式使得算法操作的添加比较容易。
- 如果一组类中,存在着相似的操作,为了避免出现大量重复的代码,可以考虑把重复的操作封装到访问者中。(当然也可以考虑使用抽象类了)
- 如果一个对象存在着一些与本身对象不相干,或关系比较弱的操作时,为了避免操作污染这个对象,则可以考虑把这些操作封装到访问者对象中。
访问者模式的优缺点
访问者模式具有以下优点:
- 访问者模式使得添加新的操作变得容易。如果一些操作依赖于一个复杂的结构对象的话,那么一般而言,添加新的操作会变得很复杂。而使用访问者模式,增加新的操作就意味着添加一个新的访问者类。因此,使得添加新的操作变得容易。
- 访问者模式使得有关的行为操作集中到一个访问者对象中,而不是分散到一个个的元素类中。这点类似与"中介者模式"。
- 访问者模式可以访问属于不同的等级结构的成员对象,而迭代只能访问属于同一个等级结构的成员对象。
访问者模式也有如下的缺点:
- 增加新的元素类变得困难。每增加一个新的元素意味着要在抽象访问者角色中增加一个新的抽象操作,并在每一个具体访问者类中添加相应的具体操作。