程序设计: 猫大叫一声,所有的老鼠都开始逃跑,主人被惊醒。(C#语言)
要求: 1.要有联动性,老鼠和主人的行为是被动的。
2.考虑可扩展性,猫的叫声可能引起其他联动效应。
看了这题目觉得很有意思,仔细一想其实就是一个观察者的模式,用模式的术语来讲:
鼠和人都在观察者的立场上,猫则是被观察的主体:
详细讲来,要点有三:


想清楚了上面的时序,就不难定义程序所需要的接口,一个简单的示例如下:
public
interface
IObserver

...
{
string Name

...{
get;
set;
}

/**//// <summary>
/// 主体发生变化后,观察者获得“通知”的方法
/// </summary>
void Response();
}


public
interface
ISubject

...
{
//主体需要提供“注册”方法,观察者可以注册自己感兴趣的内容
void Register(IObserver observer);
//主体需要提供“撤销注册”方法,观察者可以不再观察
void Unregister(IObserver observer);

}

/**/
/// <summary>
/// 主体:猫
/// </summary>
public
class
Cat : ISubject

...
{
List<IObserver> observers;

public Cat()

...{
observers = new List<IObserver>();
}


ISubject Members#region ISubject Members

public void Register(IObserver observer)

...{
//使用容器来存储所有的观察者的实例
observers.Add(observer);
}

public void Unregister(IObserver observer)

...{
//把观察者从容器中移除
observers.Remove(observer);

}



/**//// <summary>
/// 此函数用来模拟主体发生变化,并“通知”所有的观察者
/// </summary>
public void Cry()

...{
foreach (IObserver obs in observers)

...{
obs.Response();
}
}


#endregion


ISubject Members#region ISubject Members


#endregion
}
/**/
/// <summary>
/// 观察者:鼠
/// </summary>
public
class
Mouse : IObserver

...
{


private string _name;


public Mouse(string name, ISubject subject)

...{
_name = name;
subject.Register(this);

}



IObserver Members#region IObserver Members

public string Name

...{
get

...{
return _name;
}
set

...{
_name = value;
}
}

public void Response()

...{
Console.WriteLine( this.Name + ":" + "run---------->");
}

#endregion
}


/**/
/// <summary>
/// 观察者:人
/// </summary>
public
class
Master : IObserver

...
{

private string _name;

public Master(string name,ISubject subject)

...{
_name = name;
subject.Register(this);

}


IObserver Members#region IObserver Members

public string Name

...{
get

...{
return _name;
}
set

...{
_name = value;
}
}

public void Response()

...{
Console.WriteLine("master woke up");
}

#endregion
}

客户端代码:
class
MainClass

...
{
public static void Main(string[] args)

...{
Cat cat = new Cat();
Mouse m1 = new Mouse("miky", cat);
Mouse m2 = new Mouse("doll", cat);
Mouse m3 = new Mouse("benn", cat);
Mouse m4 = new Mouse("bond", cat);
Master m = new Master("Bennyxu", cat);
cat.Cry();

cat.Unregister(m);
Console.WriteLine(" after master has unregisted");
cat.Cry();
Console.ReadLine();


}


}
输出:
如果你熟悉.NET的事件模型的话,你会发现Delegate + Event会很容易达到这种效果。一个简单的示例如下:
public
delegate
void
StateChangedHandler();


/**/
/// <summary>
/// 主体:被观察的对象
/// </summary>
public
abstract
class
Subject

...
{
public event StateChangedHandler SubjectStateChanged;

protected void OnStateChanged()

...{
if (SubjectStateChanged != null)

...{
SubjectStateChanged();
}
}



}


/**/
/// <summary>
/// 观察者
/// </summary>
public
abstract
class
Observer

...
{
public Observer(Subject subject)

...{
//将Delegate绑定观察者的方法,与主体的事件关联
subject.SubjectStateChanged += new StateChangedHandler(Response);

}


/**//// <summary>
/// 观察者获得通知的方法(Delegate绑定到观察者的方法)
/// </summary>
public abstract void Response;

}




public
class
Mouse2 : Observer

...
{
private string _name;

public Mouse2(string name, Subject subject)
: base(subject)

...{
_name = name;
}
public override void Response()

...{
Console.WriteLine(_name + "run");
}
}



public
class
Master2 : Observer

...
{
public Master2(Subject subject)
: base(subject)

...{
}

public override void Response()

...{
Console.WriteLine("master woke up!!");
}
}


public
class
Cat2 : Subject

...
{

/**//// <summary>
/// 模拟主体发生变化
/// </summary>
public void Cry()

...{
base.OnStateChanged();
}


/**//// <summary>
/// 指定的观察者撤销对主体的观察
/// </summary>
/// <param name="observer"></param>
public void Unregister(Observer observer)

...{
base.SubjectStateChanged -= new StateChangedHandler(observer.Response);
}

}


class
MainClass

...
{
public static void Main(string[] args)

...{
Cat2 cat = new Cat2();
Mouse2 m1 = new Mouse2("miky", cat);
Mouse2 m2 = new Mouse2("doll", cat);
Mouse2 m3 = new Mouse2("benn", cat);
Mouse2 m4 = new Mouse2("bond", cat);
Master2 m = new Master2(cat);
cat.Cry();


cat.Unregister(m);
Console.WriteLine("after remove master observer:");
cat.Cry();

Console.ReadLine();
}


}
