设计模式随笔-发大米喽 (转)
吕震宇
每年到这个时候,工会都要给每位教工发大米、油什么的。正好我家的米快吃完了,所以这两天就盼着发大米,可是等了好多天也没见什么动静,扳着手指头数数离年根还有多半个月呢,看我心急的。不过,盼大米的老师恐怕不只是我一个,都等着工会有什么动静就去领大米呢。
其实,这里面还有很多东西可以拿来说说呢。教工等着发大米是一个典型的观察者模式,当工会大米来了,教工就会做出响应。不过这观察也有两种说头:一种是拉(Pull)模式,要求教工时不时到工会绕一圈,看看大米来了没有,恐怕没有人认为这是一种好办法。当然,还有另外一种模式,就是推(Push)模式,大米到了工会,工会会给每家每户把大米送过去。第二种方法好不好呢?好~~~~~呀!呵呵,谁说好了,谁说好我让谁到工会上班去。
其实,我们还有一种方法,就是大米到了工会后,工会不把大米给每人送去,而是给每人发个轻量级的"消息",教工得到消息后,再把大米"拉"回各家。这要求每位教工有一个工会的引用,在得到消息后到指定的地点领取大米。这样工会不用给每家教工送大米,而教工也不用每天到工会门口巴望着等大米了。
如果用代码来描述的化,就是这样一个观察者模式:
using System;
using System.Collections;
public class Teacher
{
private string name = "";
private GongHui g;
public Teacher(string name, GongHui g)
{
this.name = name;
this.g = g;
}
public void RiceArrived()
{
Console.WriteLine("{0}收到领大米的消息。", name);
g.GetRice();
}
}
public class Subject
{
protected ArrayList teachers = new ArrayList();
protected void Notify()
{
foreach(Teacher t in teachers)
t.RiceArrived();
}
public void Subscribe(Teacher s)
{ teachers.Add(s); }
}
public class GongHui : Subject
{
private int RiceLeft = 0;
public void RiceArrived(int n)
{
this.RiceLeft = n;
Notify();
}
public void GetRice()
{
if(RiceLeft > 0)
Console.WriteLine("还剩 {0} 袋大米", --RiceLeft);
else
Console.WriteLine("抱歉,大米发完了,等下一拨吧。");
}
}
public class Client
{
public static void Main( string[] args )
{
GongHui g = new GongHui();
g.Subscribe(new Teacher("张三",g));
g.Subscribe(new Teacher("李四",g));
g.Subscribe(new Teacher("王五",g));
g.RiceArrived(2);
}
}
using System.Collections;
public class Teacher
{
private string name = "";
private GongHui g;
public Teacher(string name, GongHui g)
{
this.name = name;
this.g = g;
}
public void RiceArrived()
{
Console.WriteLine("{0}收到领大米的消息。", name);
g.GetRice();
}
}
public class Subject
{
protected ArrayList teachers = new ArrayList();
protected void Notify()
{
foreach(Teacher t in teachers)
t.RiceArrived();
}
public void Subscribe(Teacher s)
{ teachers.Add(s); }
}
public class GongHui : Subject
{
private int RiceLeft = 0;
public void RiceArrived(int n)
{
this.RiceLeft = n;
Notify();
}
public void GetRice()
{
if(RiceLeft > 0)
Console.WriteLine("还剩 {0} 袋大米", --RiceLeft);
else
Console.WriteLine("抱歉,大米发完了,等下一拨吧。");
}
}
public class Client
{
public static void Main( string[] args )
{
GongHui g = new GongHui();
g.Subscribe(new Teacher("张三",g));
g.Subscribe(new Teacher("李四",g));
g.Subscribe(new Teacher("王五",g));
g.RiceArrived(2);
}
}
有关观察者模式的更多信息,请参考《设计模式(19)-Observer Pattern》。