如果知道一个“事件”概念就“不知道怎么好了”,把一个简单的事件(作为模式)夸大到这种实际设计要求上,正如你所说的,距离“真正实现它”还差一大截。因此弄出来几个基本的模式名词儿,几乎还不能直截了当地看出任何具体问题。 我们假设什么“事件、观察者、委托、状态”之类的都是你所知道的名词儿,我们直接讨论高级一点的设计问题。实际上可以有各种办法来进行设计。我们举出一种类似于MVVM的方式。以“手表”的界面为基础,假设我们的美工人员使用 Blend 来开发一个 WPF 或者 silverlight 的“手表”,我们把View根ViewModel分离开进行设计,手表实际上需要有多个不同的ViewModel进行切换。一个产品经理需要先在文档中详细描述ViewModel机制,交给小程序员去开发(然后美工可以在 Blend 上加入到“手表”中)。多个ViewModel统一地都具有相同的模式using System; using System.ComponentModel;public abstract class 手表Model : INotifyPropertyChanged { public virtual void 按钮1压下(); public virtual void 按钮2压下(); public virtual void 按钮3压下(); public virtual void 按钮2和3压下(); private DateTime _时间; public DateTime 时间 { get { return _时间; } set { if (value != _时间) { _时间 = value; if (this.PropertyChanged != null) this.PropertyChanged(this, new PropertyChangedEventArgs("时间")); } } } private bool _是否哔哔响; public bool 是否哔哔响 { get { return _是否哔哔响; } set { if (value != _是否哔哔响) { _是否哔哔响 = value; if (this.PropertyChanged != null) this.PropertyChanged(this, new PropertyChangedEventArgs("是否哔哔响")); } } } public event Action<手表Model> 改变数据模型; protected void On改变数据模型(手表Model newModel) { if (this.改变数据模型 != null) this.改变数据模型(newModel); } public event PropertyChangedEventHandler PropertyChanged; }这个ViewModel说明了, 1. 手表View关心两种用户可见的界面:“显示时间、是否哔哔响”。手表的表盘上的数字可以与“时间”属性绑定起来,同时一个行为模式绑定到“是否哔哔响”的属性改变事件上。 2. 手表View要捕获3个按键的4种按键操作,并且在各自行为中执行ViewModel的那4个方法。但是它们只有到子类中才能具体定义。 3. 当一个ViewModel需要通知View改变状态(因为状态复杂多变,所以设计为可变的,而不是一个大而全的),那么View要将一个行为绑定到这个事件上,获取事件抛出的、新的“手表Model”实例对象,并更新自己之前绑定的DataContext。再来看具体的ViewModel就比较简单了。它们必须做的不过是: 1. 在各自内部实现“1秒、30秒”定时处理。或者是修改显示时间,或者是通知宿主“应该切换到某个新的数据模型了”。 2. 实现4个操作的内部处理。也就是调整时间。
上面把 abstract 写成 virtual 了,请自己修改一下。随便写的代码,看懂就可以了。
//simple Observer_patternusing System; using System.Collections.Generic; using System.Text.RegularExpressions; using System.Threading; using Timer = System.Timers.Timer;namespace ConsoleApplication1 { class Program { static void Main() { new Client().Run(); } } public class Client :ITask1 { private readonly Onesec _xxx = new Onesec(); public void Run() { _xxx.AddObserver(new Timer1SService()); _xxx.AddObserver(new Timer2SService()); var customEvent = new CustomEvent("Task1",this); _xxx.Notify(customEvent); } public void ShowTime(DateTime a) { Console.WriteLine(a); }
} public interface IObserver { void UpdateStatus(ISubject s, CustomEvent e); } public interface ISubject { void AddObserver(IObserver observer); void RemoveObserver(IObserver observer); void Notify( CustomEvent e); } public class Onesec : ISubject { private readonly IList<IObserver> _db = new List<IObserver>(); public void AddObserver(IObserver observer) { _db.Add(observer); } public void RemoveObserver(IObserver observer) { _db.Remove(observer); } public void Clear() { _db.Clear(); } public void Notify( CustomEvent e) { foreach (var observer in _db) { observer.UpdateStatus(this,e); } } } public class Timer1SService : IObserver { private readonly AutoResetEvent _t = new AutoResetEvent(false); public void UpdateStatus(ISubject s, CustomEvent e) { if (Regex.IsMatch(e.M, "Task1")) {
var thread = new Thread(o => { var task1 = (ITask1)e.S; var timer = new Timer(1000) { AutoReset = false, Enabled = true }; timer.Elapsed += (sender, args) => { task1.ShowTime(args.SignalTime); _t.Set(); }; timer.Start(); while (true) { WaitHandle.WaitAll(new WaitHandle[] {_t}); break; } }); thread.Start(); thread.Join(); } } } public class Timer2SService : IObserver { private readonly AutoResetEvent _t = new AutoResetEvent(false); public void UpdateStatus(ISubject s, CustomEvent e) { if (Regex.IsMatch(e.M, "Task1")) { var thread = new Thread(o => { var task1 = (ITask1)e.S; var timer = new Timer(2000) { AutoReset = false, Enabled = true }; timer.Elapsed += (sender, args) => { task1.ShowTime(args.SignalTime); _t.Set(); }; timer.Start(); while (true) { WaitHandle.WaitAll(new WaitHandle[] { _t }); break; } }); thread.Start(); thread.Join(); } } }
public class CustomEvent { public string M { get; set; } public object S { get; set; } public CustomEvent(string message,object self) { M = message; S = self; } } public interface ITask1 { void ShowTime(DateTime a); } }
我们假设什么“事件、观察者、委托、状态”之类的都是你所知道的名词儿,我们直接讨论高级一点的设计问题。实际上可以有各种办法来进行设计。我们举出一种类似于MVVM的方式。以“手表”的界面为基础,假设我们的美工人员使用 Blend 来开发一个 WPF 或者 silverlight 的“手表”,我们把View根ViewModel分离开进行设计,手表实际上需要有多个不同的ViewModel进行切换。一个产品经理需要先在文档中详细描述ViewModel机制,交给小程序员去开发(然后美工可以在 Blend 上加入到“手表”中)。多个ViewModel统一地都具有相同的模式using System;
using System.ComponentModel;public abstract class 手表Model : INotifyPropertyChanged
{
public virtual void 按钮1压下();
public virtual void 按钮2压下();
public virtual void 按钮3压下();
public virtual void 按钮2和3压下(); private DateTime _时间; public DateTime 时间
{
get { return _时间; }
set
{
if (value != _时间)
{
_时间 = value;
if (this.PropertyChanged != null)
this.PropertyChanged(this, new PropertyChangedEventArgs("时间"));
}
}
} private bool _是否哔哔响; public bool 是否哔哔响
{
get { return _是否哔哔响; }
set
{
if (value != _是否哔哔响)
{
_是否哔哔响 = value;
if (this.PropertyChanged != null)
this.PropertyChanged(this, new PropertyChangedEventArgs("是否哔哔响"));
}
}
} public event Action<手表Model> 改变数据模型; protected void On改变数据模型(手表Model newModel)
{
if (this.改变数据模型 != null)
this.改变数据模型(newModel);
} public event PropertyChangedEventHandler PropertyChanged;
}这个ViewModel说明了,
1. 手表View关心两种用户可见的界面:“显示时间、是否哔哔响”。手表的表盘上的数字可以与“时间”属性绑定起来,同时一个行为模式绑定到“是否哔哔响”的属性改变事件上。
2. 手表View要捕获3个按键的4种按键操作,并且在各自行为中执行ViewModel的那4个方法。但是它们只有到子类中才能具体定义。
3. 当一个ViewModel需要通知View改变状态(因为状态复杂多变,所以设计为可变的,而不是一个大而全的),那么View要将一个行为绑定到这个事件上,获取事件抛出的、新的“手表Model”实例对象,并更新自己之前绑定的DataContext。再来看具体的ViewModel就比较简单了。它们必须做的不过是:
1. 在各自内部实现“1秒、30秒”定时处理。或者是修改显示时间,或者是通知宿主“应该切换到某个新的数据模型了”。
2. 实现4个操作的内部处理。也就是调整时间。
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Threading;
using Timer = System.Timers.Timer;namespace ConsoleApplication1
{
class Program
{
static void Main()
{
new Client().Run();
}
} public class Client :ITask1
{
private readonly Onesec _xxx = new Onesec(); public void Run()
{
_xxx.AddObserver(new Timer1SService());
_xxx.AddObserver(new Timer2SService());
var customEvent = new CustomEvent("Task1",this);
_xxx.Notify(customEvent);
}
public void ShowTime(DateTime a)
{
Console.WriteLine(a);
}
} public interface IObserver
{
void UpdateStatus(ISubject s, CustomEvent e);
} public interface ISubject
{
void AddObserver(IObserver observer);
void RemoveObserver(IObserver observer);
void Notify( CustomEvent e);
} public class Onesec : ISubject
{ private readonly IList<IObserver> _db = new List<IObserver>(); public void AddObserver(IObserver observer)
{
_db.Add(observer);
} public void RemoveObserver(IObserver observer)
{
_db.Remove(observer);
} public void Clear()
{
_db.Clear();
} public void Notify( CustomEvent e)
{
foreach (var observer in _db)
{
observer.UpdateStatus(this,e);
}
} } public class Timer1SService : IObserver
{
private readonly AutoResetEvent _t = new AutoResetEvent(false); public void UpdateStatus(ISubject s, CustomEvent e)
{ if (Regex.IsMatch(e.M, "Task1"))
{
var thread = new Thread(o =>
{
var task1 = (ITask1)e.S;
var timer = new Timer(1000) { AutoReset = false, Enabled = true };
timer.Elapsed += (sender, args) =>
{
task1.ShowTime(args.SignalTime);
_t.Set();
};
timer.Start(); while (true)
{
WaitHandle.WaitAll(new WaitHandle[] {_t});
break;
}
}); thread.Start();
thread.Join(); } }
} public class Timer2SService : IObserver
{
private readonly AutoResetEvent _t = new AutoResetEvent(false); public void UpdateStatus(ISubject s, CustomEvent e)
{
if (Regex.IsMatch(e.M, "Task1"))
{ var thread = new Thread(o =>
{
var task1 = (ITask1)e.S;
var timer = new Timer(2000) { AutoReset = false, Enabled = true };
timer.Elapsed += (sender, args) =>
{
task1.ShowTime(args.SignalTime);
_t.Set();
};
timer.Start(); while (true)
{
WaitHandle.WaitAll(new WaitHandle[] { _t });
break;
}
}); thread.Start();
thread.Join();
}
}
}
public class CustomEvent
{
public string M { get; set; }
public object S { get; set; } public CustomEvent(string message,object self)
{
M = message;
S = self;
}
} public interface ITask1
{
void ShowTime(DateTime a);
}
}
INotifyPropertyChanged这个接口能不能说说都有什么成员和作用呀
{
class Program
{
static void Main(string[] args)
{
//老板胡汉三
Boss huhansan = new Boss(); //看股票的同事
StockObserver tongshi1 = new StockObserver("魏关姹", huhansan);
//看NBA的同事
NBAObserver tongshi2 = new NBAObserver("易管查", huhansan); huhansan.Update += new EventHandler(tongshi1.CloseStockMarket);
huhansan.Update += new EventHandler(tongshi2.CloseNBADirectSeeding); //老板回来
huhansan.SubjectState = "我胡汉三回来了!";
//发出通知
huhansan.Notify(); Console.Read();
}
} //通知者接口
interface Subject
{
void Notify();
string SubjectState
{
get;
set;
}
} //事件处理程序的委托
delegate void EventHandler(); class Secretary : Subject
{
//声明一事件Update,类型为委托EventHandler
public event EventHandler Update; private string action; public void Notify()
{
Update();
}
public string SubjectState
{
get { return action; }
set { action = value; }
}
} class Boss : Subject
{
//声明一事件Update,类型为委托EventHandler
public event EventHandler Update; private string action; public void Notify()
{
Update();
}
public string SubjectState
{
get { return action; }
set { action = value; }
}
} //看股票的同事
class StockObserver
{
private string name;
private Subject sub;
public StockObserver(string name, Subject sub)
{
this.name = name;
this.sub = sub;
} //关闭股票行情
public void CloseStockMarket()
{
Console.WriteLine("{0} {1} 关闭股票行情,继续工作!", sub.SubjectState, name);
}
} //看NBA的同事
class NBAObserver
{
private string name;
private Subject sub;
public NBAObserver(string name, Subject sub)
{
this.name = name;
this.sub = sub;
} //关闭NBA直播
public void CloseNBADirectSeeding()
{
Console.WriteLine("{0} {1} 关闭NBA直播,继续工作!", sub.SubjectState, name);
}
}一个事件发生后 查看,通知,操作多个类 怎么样??