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

    慢慢的做记录,做最强大的自己

    看了大话设计模式之后感触很深,发现自己还有很多学习的东西,设计软件并不是一两句代码把功能写完了就行,需要思考的内容有很多

    代码来源参考大话设计模式这本书,这里在博客里记录一下,不可能每次都去翻书,但是在博客里面是非常好找的。

            观察者模式(Observer)算是设计模式里面最经典的一个模式了,这个模式可以应用在业务逻辑处理与界面交互的过程中,官方解释就是在此种模式中,

    一个目标物件管理所有相依于它的观察者物件,并且在它本身的状态改变时主动发出通知。这通常透过呼叫各观察者所提供的方法来实现。此种模式通常被用来实现事件处理系统。

    举一个简单的例子,之前看到的面试题:

    猫看见很多老鼠在偷米吃,大叫了一声,主人醒了,这就是一个经典的观察者模式,老鼠跟主人都是观察者(Observer),而猫是一个被观察者(Subject)

    之前我同事还给我举了一个例子:项目经理,前台妹纸,还有科室成员,怎么防止项目经理突然间在同事都在做非工作上的事情时,提前预知,那么就需要前台妹纸去观察了。

    那么怎么去实现观察者模式呢,那就是把观察者当一个整体给抽象出来。

    就以猫遇见老鼠叫主人被惊醒这个为例子:

        首先,理解一下观察者是谁,这里面谁跟谁是什么关系,老鼠遇见猫又是什么反应,猫叫声对主人又产生了什么影响

     public interface Observer
        {
            void Response();    //观察者的响应,如是老鼠见到猫的反映
        }
        public interface Subject
        {
            void AimAt(Observer obs);  //针对哪些观察者,这里指猫的要扑捉的对象---老鼠,还有猫惊醒的主人
        }

    老鼠见到猫的反应用一个类写出来

    public class Mouse : Observer
        {
            private string name;
            public Mouse(string name, Subject subj)
            {           
                this.name = name;
                subj.AimAt(this);
            }
            
            public void Response()
            {
                Console.WriteLine(name + " 开始逃窜!");
            }
        }

    然后主人被猫叫声吵醒,也是一个反应,这里继承观察者

    public class Master : Observer
        {   
            public Master(Subject subj)
            {           
                subj.AimAt(this);
            }
            
            public void Response()
            {
                Console.WriteLine("吵死了!");
            }  
        }

    猫是被观察者,主要产生的行为就是大叫一声

     public class Cat : Subject
        {
            private ArrayList observers;
            public Cat()
            {   
                this.observers = new ArrayList();
            }
            public void AimAt(Observer obs)
            {
                this.observers.Add(obs);
            }
            public void Cry()
            {
                Console.WriteLine("猫大叫一声!");
                foreach (Observer obs in this.observers)
                {
                    obs.Response();
                }
            }
        }

    整个过程在客户端的代码就是这样的

    class MainClass
        {       
            static void Main(string[] args)
            {
                Cat cat = new Cat();
                Mouse mouse1 = new Mouse("mouse1", cat);
                Mouse mouse2 = new Mouse("mouse2", cat);
                Master master = new Master(cat);
                cat.Cry();
            }
        }

    当然这里耦合程度还是很高,主人跟老鼠的行为都是高度依赖猫这个抽象的观察者,怎么改才能解耦,那么就需要用到另外一种方式:事件委托

    这里声明了一个委托事件

    public delegate void SubEventHandler();
        public abstract class Subject
        {
            public event SubEventHandler SubEvent;
            protected void FireAway()
            {
                if (this.SubEvent != null)
                    this.SubEvent();
            }   
        }

    猫对被观察者的影响

    class Cat : Subject
        {
            public new event SubEventHandler SubEvent;
    
            public void Cry()
            {
                SubEvent();
                Console.WriteLine("猫大叫!");
                
            }
            
        }

    然后老鼠跟主人都被猫影响,观察者被被观察者影响,产生不同的反应

    interface Observer
        {
            void Response();    //观察者的响应,如是老鼠见到猫的反映
        }

    老鼠观察者的响应,产生逃跑反应

    class MouseObserver
        {
            private string name;
            public MouseObserver(string name, Subject subj)
            {
                this.name = name;
    
            }
    
            public void Response()
            {
                Console.WriteLine(name + " 赶紧逃离!");
            }
    
        }

    主人观察者的反应,吵死了

     class MasterObserver
        {
            private string name;
            public MasterObserver(string name, Subject subj)
            {
                this.name = name;
            }
    
            public void Response()
            {
                Console.WriteLine(name + ":吵死了!");
            }
    
        }

    然后在交互端反馈出来是这样的:

    static void Main(string[] args)
            {
                Cat cat = new Cat();
                MouseObserver mouse1 = new MouseObserver("mouse1", cat);
                MouseObserver mouse2 = new MouseObserver("mouse2", cat);
                MasterObserver Master = new MasterObserver("主人", cat);
                cat.SubEvent += new SubEventHandler(mouse1.Response);
                cat.SubEvent += new SubEventHandler(mouse2.Response);
                cat.SubEvent += new SubEventHandler(Master.Response);
                cat.Cry();
                Console.ReadLine();
            }

    查看运行结果如下:

    这样处理过程就在客户端进行,就不需要依赖抽象观察者了

  • 相关阅读:
    如何使用BackgroundWorker
    Start SQL Service failed with message: "the log scan number passed to log scan in database 'master' is not valid"
    Cmdkey 凭证管理器工具
    PowerShell根据下载link下载文件
    vnc远程到连接linux服务器。
    shell远程取数据的脚本.
    about开源监控nagios.
    Android入门:File文件存储
    Android入门:Layout
    Android入门:Log介绍
  • 原文地址:https://www.cnblogs.com/yinxuejunfeng/p/9630128.html
Copyright © 2011-2022 走看看