http://en.wikipedia.org/wiki/Observer_pattern

解决方案 »

  1.   

    如果知道一个“事件”概念就“不知道怎么好了”,把一个简单的事件(作为模式)夸大到这种实际设计要求上,正如你所说的,距离“真正实现它”还差一大截。因此弄出来几个基本的模式名词儿,几乎还不能直截了当地看出任何具体问题。
    我们假设什么“事件、观察者、委托、状态”之类的都是你所知道的名词儿,我们直接讨论高级一点的设计问题。实际上可以有各种办法来进行设计。我们举出一种类似于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个操作的内部处理。也就是调整时间。
      

  2.   

    上面把 abstract 写成 virtual 了,请自己修改一下。随便写的代码,看懂就可以了。
      

  3.   

    //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);
        }
    }
      

  4.   

    从你第一张图上来看,你有6个手表ViewModel需要单独开发。从你的第二张图来看,可以看出不同ViewModel内部的实现的部分差别。因此你贴的这两张图,非常精确,非常好的设计素材。日本的程序设计,跟日本女优一样,都比较深入实际。
      

  5.   

    编程的目的,当然是少写代码。如果能够少定义一些class,傻瓜才会书呆子似地专门多弄class出来!可是有的人就是弄好多class出来,而你仔细看,却发现没有直截了当地“接地气”。写一大堆东西只是为了弄很简单的东西,而最终需要的东西却不能迅速表达出来,这就是空谈模式了。但是虽然我们追求“尽量少定义class,尽量少写代码”来进行程序开发,我们仍然要讲求模式。因此模式没有是非,只有“是否适合”。一定要变换不同的模式,来解决同一个问题。并最终避免再去抄写那些过于抽象而内涵太少的顶层的东西。
      

  6.   


    INotifyPropertyChanged这个接口能不能说说都有什么成员和作用呀
      

  7.   

    namespace 观察者模式
    {
        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);
            }
        }一个事件发生后 查看,通知,操作多个类 怎么样??