zoukankan      html  css  js  c++  java
  • 设计模式之观察者模式

    观察者模式

    观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态上发生变化时,会通知所有观察者对象,使它们能够自动更新自己

     1. Subject是对主题的抽象,但具体维护通知对象是在子类ConcreteSubject的实现中,ConcreteSubject调用它的notify来遍历通知对象。

     2. ConcreteSubject是具体的主题,也是我们关心的对象,当它的subjectState修改的时候,同时调用父类的notify.实现通知

    3. 当一个对象需要通知或改变其它对象,而它又不能假定其它对象是谁,也就是说 ,不希望这些对象是紧耦合的,我们就可能考虑它

    观察者模在通信的具体实现中,有两个版本。

    1) 拉模式:目标角色在发生变化后,仅仅告诉观察者角色“我变化了”;观察者角色如果想要知道具体的变化细节,则就要自己从目标角色的接口中得到。拉模式是想要就主动表白获取。这里存在依赖,观察者要依赖具体的主题 。

    2) 推模式:通知你发生变化的同时,通过一个参数将变化的细节传递到观察者角色中去。推模式是管你要不要,先给你啦。推模型可能会使得观察者对象难以复用,因为观察者的update()方法是按需要定义的参数,可能无法兼顾没有考虑到的使用情况

    而拉模型就不会造成这样的情况,因为拉模型下,update()方法的参数是主题对象本身,这基本上是主题对象能传递的最大数据集合了,基本上可以适应各种情况的需要

     以下是拉模式 代码如下: 实现的逻辑:当门打开时,主卧和客厅的灯亮起,电视打开。

    /// <summary>
        /// 抽象主题 
        /// </summary>
        public abstract class Subject
        {
            private List<Observer> observers = new List<Observer>();
    
            public void Add(Observer observer)
            {
                observers.Add(observer);
            }
            public void Remove(Observer observer)
            {
                observers.Remove(observer);
            }
    
            /// <summary>
            /// 通知所有观察者
            /// </summary>
            public void Notify()
            {
                observers.ForEach(o => o.Action(this));
            }
        }
    
        public class Door :Subject
        {
            public string DoorState { get; set; }
            public void Open()
            {
                this.DoorState = "开启";
    
                Console.WriteLine(string.Format("门开起"));
                base.Notify();
            }
        }
    
        public abstract class Observer
        {
            public abstract void Action(Subject subject);
        }
    
        public class Light : Observer
        {
            private string name;
    
            public Light(string name)
            {
                this.name = name;
            }
            public override void Action(Subject subject)
            {
                var door = (Door)subject;
                
                Console.WriteLine(string.Format("门{0},{1}灯 亮起",door.DoorState, this.name));
            }
        }
    
        public class TV : Observer
        {
            public override void Action(Subject subject)
            {
                Console.WriteLine(string.Format("TV 打开"));
            }
        }
    
        class Program
        {
            static void Main(string[] args)
            {
                Console.OutputEncoding = Encoding.UTF8;
    
                Observer masterRoom = new Light("主卧室");
                Observer LivingRoom = new Light("客厅");
                Observer tv = new TV();
    
                Door door = new Door();
                door.Add(masterRoom);
                door.Add(LivingRoom);
                door.Add(tv);
    
                door.Open();
    
                Console.ReadKey();
            }
        }

    C# 提供了事件的机制,同样可以实现观察者模式,与上面代码稍有不同:

    //继承自EventArgs
        //用作保存状态,还可以扩展其他的功能
        public class StateChangeEventArgs : EventArgs
        {
            public string State { get; set; }
            public StateChangeEventArgs(string state)
            {
                this.State = state;
            }
        }
    
        //定义一个委托 
        public delegate void StateChangeEventHandler(object sender, StateChangeEventArgs e);
    
        public class Door
        {
            public event StateChangeEventHandler StateChange;
    
            public string DoorState { get; set; }
            public void Open()
            {
                this.DoorState = "开启";
    
                Console.WriteLine(string.Format("门开起"));
                StateChangeEventArgs e = new StateChangeEventArgs(this.DoorState);
                StateChange(this, e);
            }
        }
    
        public abstract class Observer
        {
            public abstract void Action(object sender, StateChangeEventArgs e);
        }
    
        public class Light : Observer
        {
            private string name;
    
            public Light(string name)
            {
                this.name = name;
            }
            public override void Action(object sender, StateChangeEventArgs e)
            {
    
                Console.WriteLine(string.Format("门{0},{1}灯 亮起", e.State, this.name));
            }
        }
    
        public class TV : Observer
        {
            public override void Action(object sender, StateChangeEventArgs e)
            {
                Console.WriteLine(string.Format("TV 打开"));
            }
        }
    
        class Program
        {
            static void Main(string[] args)
            {
                Console.OutputEncoding = Encoding.UTF8;
    
                Observer masterRoom = new Light("主卧室");
                Observer livingRoom = new Light("客厅");
                Observer tv = new TV();
    
                Door door = new Door();
    
                door.StateChange += masterRoom.Action;
                door.StateChange += livingRoom.Action;
                door.StateChange += tv.Action;
    
                door.Open();
    
                Console.ReadKey();
            }
        }
  • 相关阅读:
    ASP.NET 后台弹出确认提示问题
    stretchableImageWithLeftCapWidth 自动适应UITableView
    UIBotton UIlabel Ios 下拉框
    cellForRowAtIndexPath UITableViewCell 选中后的背景颜色设置
    iOS 获得键盘的高度 NSNotificationCenter
    UIlabel 最小字体设置。
    NSMutableDictionary 与 NSMutableArray注意的地方
    iOS 背景图片。按钮高亮自定义背景
    iOS 判断当前输入法。UITextInputMode
    AudioServicesPlaySystemSound 系统声音提示 iOS iPad
  • 原文地址:https://www.cnblogs.com/hankuikui/p/7026897.html
Copyright © 2011-2022 走看看