文档章节

观察者模式(七)

NickHomeSelf
 NickHomeSelf
发布于 2017/08/14 00:43
字数 1504
阅读 4
收藏 0

观察者模式

定义:

我们可以把观察目标理解为主动方、发布方、主体等;把观察者理解为被动方、订阅方、观察器等。目标是整个行为链的源头,其它观察者都依赖于它的变化而作出响应。为了实现低耦合,我们不能使用“直接调用”的方式而需要利用“订阅(清单)-通知”的机制去完成设计。通俗地说就是观察者向目标“订阅”它的改变,而目标发生改变后就“通知”所有已经“订阅”了它的改变的观察者,从而执行“订阅”的内容。这种机制的好处在于降低耦合度,分工明确,目标只负责在自身状态发生改变或做出某种行为时向自身的订阅清单发出“通知”,而不是直接调用观察者的行为(方法);观察者只负责向目标“订阅”它的变化,以及定义自身在收到目标“通知”后所需要做出的具体行为(也就是订阅的内容)。就像我们向出版社订阅报刊一样,出版社有新一期报刊发行时并不是直接跟每位订阅者联系,而是“通知”订阅者名单按顺序给每位订阅者发送所订报刊。

 

优点:

通过对模型与观察者基类的分析可知,委托与事件的机制几乎消除了这两个模块之间的耦合,灵活性提高了很多。如果需要增加观察者,则只需要覆盖基类抽象方法及把观察目标传递给基类。

 

案例 1:

有一个拍卖师和诺干买家进行一个艺术品拍卖,这里我们使用观察者模式。这里的拍卖师为被观察者,买家是观察者。

 public abstract class observer//首先要创建一个观察者基类
{
    public abstract void QuotedPrice();//观察者的报价
       
}




 public abstract class Subject//拍卖者基类
    {
        public ArrayList observers = new ArrayList();//用于存储观察者的数组
        public int _price;//拍卖价格

        public void AddObserver(observer person)//添加观察者
        {
            observers.Add(person);
            Console.WriteLine("......{0}加入拍卖",person);
        }

        public void DeleteObserver(observer person)//删除观察者
        {
            observers.Remove(person);
            Console.WriteLine("......{0}退出拍卖", person);
        }

        public virtual void QuotedPrice()//通知每一个观察者现在的价格
        {
            for (int i = observers.Count - 1; i >= 0 ; i--)
            {
                ((observer)observers[i]).QuotedPrice();
            }
        }

        public bool IsOver//是否拍卖结束
        {
            get
            {
                if (observers.Count == 0 || observers.Count == 1)
                    return true;
                else
                    return false;
            }
        }
    }



 public class SubjectArt:Subject//具体的拍卖者类
    {
        public SubjectArt(int _price)//构造函数,构造时,确定起拍价。
        {
            this._price = _price;
        }

        public int Price//现在的拍卖价格
        {
            get
            {
                return this._price;
            }
            set
            {
                if (this._price > value)
                    return;
                else
                    _price = value;
            }
        }

        public override void QuotedPrice()//拍卖者出家
        {
            base.QuotedPrice();

            if (observers.Count == 1)
            {
                Console.WriteLine("{0}最终胜出,最终报价为{1}", observers[0], this.Price);
            }
            else if (observers.Count == 0)
            {
                Console.WriteLine("本次竞拍流拍...");
            }


        }
    }



public class observerArt:observer//具体的买家类
    {
        private int _price;//当前买家的出家
        private int _topPrice;//买家最高的心理价位
        private string _name;//买家的名字

        private SubjectArt _subjectArt;//持有拍卖者的引用
        public observerArt(string Name,int price,int topPrice, SubjectArt subjectArt)//根据参数进行构造,并把自己作为买家注册给拍卖者
        {
            this._name = Name;
            this._price = price;
            this._topPrice = topPrice;
            this._subjectArt = subjectArt;
            this._subjectArt.AddObserver(this);
        }
        public override void QuotedPrice()//买家是否再进行出家或者退出
        {
            if (this._price > _topPrice)
            {
                Console.WriteLine("{0}退出,当前最高价格{1}", this._name, _subjectArt._price);
                this._subjectArt.DeleteObserver(this);
            }
            else
            {
                this._price += 1;
                this._subjectArt.Price = this._price;
                if (this._price >= this._subjectArt.Price)
                {
                    Console.WriteLine("{0}报出最新价格:{1}",this._name,this._price);       
                }

            }
        }
    }







==================================进行测试===================================================
 class Program
    {
        static void Main(string[] args)
        {
            SubjectArt subjectArt = new SubjectArt(5);
            observerArt personOne = new observerArt("张晓坤",5,15, subjectArt);
            observerArt personTwo = new observerArt("张婷婷", 5, 13, subjectArt);
            observerArt personThree = new observerArt("王小明", 5, 11, subjectArt);
            observerArt personFour = new observerArt("李丽", 5, 14, subjectArt);
            observerArt personFive = new observerArt("刘伟", 5, 10, subjectArt);
            int n = 0;
            while (!subjectArt.IsOver)
            {
                Console.WriteLine("====第{0}轮竞拍========",n);
                subjectArt.QuotedPrice();
                n++;
            }
            Console.ReadKey();

        }
    }

案例2:

有一个劫匪抢劫了一家银行后逃跑了,有警察追捕他,好心市民看到劫匪会通知警察,劫匪的妻子知道劫匪缺钱后会给他汇钱。这样我们用观察者模式来描述这些,劫匪是被观察者,而警察、好心市民和劫匪妻子都是观察者。以下为代码:

  public abstract class ObserverMan//观察者的抽象类
    {
        public abstract void Update();
        
    }


 public abstract class SubjectMan//被观察者的抽象类
    {
        public List<ObserverMan> observers = new List<ObserverMan>();//所有观察者存储集合
        public string location = "";//劫匪要逃亡的地点

       
        /// <summary>
        /// 添加观察者
        /// </summary>
        /// <param name="man"></param>
        public virtual void Attact(ObserverMan man)
        {
            observers.Add(man);
        }

        /// <summary>
        /// 移除观察者
        /// </summary>
        /// <param name="man"></param>
        public virtual void Dettact(ObserverMan man)
        {
            observers.Remove(man);
        }

        /// <summary>
        /// 通知所有的观察者去做某件事
        /// </summary>
        public virtual void MessageObserverAll()
        {
            for (int i = 0; i < observers.Count; i++)
            {
                observers[i].Update();
            }
        }
    }




public class SubjectBadMan:SubjectMan//具体的劫匪类
    {
        string Name;//劫匪的名字
        public SubjectBadMan(string _name)//劫匪的构造函数
        {
            this.Name = _name;
        }

        public void RunAway(string _location)//逃跑到某个地方
        {
           
            this.location = _location;
            Console.WriteLine("歹徒{0}逃到了{1}",this.Name,this.location);
            if (this.observers.Count == 0)
            {
                Console.WriteLine("你已经安全了,不用再逃亡了....");
            }
            base.MessageObserverAll();
        }

    }




 public class Police:ObserverMan//警察观察者
    {
        SubjectBadMan badMan = null;
        public Police(SubjectBadMan _badMan)
        {
            this.badMan = _badMan;
            this.badMan.Attact(this);//警察注册观察者

        }
        public override void Update()//警察要做的事
        {
            var location = this.badMan.location;
            Console.WriteLine("警察 :歹徒已经逃到了{0},赶快部署警力抓捕。",location);
        }
    }

    public class Citizen : ObserverMan//热心市民观察者
    {
        SubjectBadMan badMan = null;
        public Citizen(SubjectBadMan _badMan)
        {
            this.badMan = _badMan;
            this.badMan.Attact(this);//热心市民注册观察者
        }
        public override void Update()//热心市民要做的事
        {
            var location = this.badMan.location;
            Console.WriteLine("热心市民:歹徒已经逃到了{0},警察赶紧去抓啊", location);
        }
    }


    public class Wife : ObserverMan//妻子要做的事
    {
        SubjectBadMan badMan = null;
        public Wife(SubjectBadMan _badMan)
        {
            this.badMan = _badMan;
            this.badMan.Attact(this);//妻子注册观察者

        }
        public override void Update()
        {
            var location = this.badMan.location;
            Console.WriteLine("妻子:你到{0}了啊,我给你汇点钱", location);
        }
    }





===========================================进行测试==========================================

            SubjectMan badMan = new SubjectBadMan("张亭亭");
            ObserverMan police = new Police(badMan as SubjectBadMan);
            ObserverMan citizen = new Citizen(badMan as SubjectBadMan);
            ObserverMan wife = new Wife(badMan as SubjectBadMan);
            SubjectBadMan man;
            man = badMan as SubjectBadMan;
            man.RunAway("上海");
            Console.WriteLine();
            man.Dettact(wife);
            man.RunAway("广州");
            Console.WriteLine();
            man.Dettact(citizen);
            man.RunAway("美国");
            Console.WriteLine();
            man.Dettact(police);
            man.RunAway("澳大利亚");
            Console.WriteLine();
            Console.ReadKey();

 

使用事件和委托来实现观察者模式

 

© 著作权归作者所有

NickHomeSelf
粉丝 0
博文 64
码字总数 19755
作品 0
私信 提问
【设计模式笔记】(十六)- 代理模式

一、简述 代理模式(Proxy Pattern),为其他对象提供一个代理,并由代理对象控制原有对象的引用;也称为委托模式。 其实代理模式无论是在日常开发还是设计模式中,基本随处可见,中介者模式中...

MrTrying
2018/06/24
0
0
EasyToLearnDesignPattern

简单上手设计模式 GITHUB:https://github.com/Fisher-Joe/EasyToLearnDesignPattern 本文旨在使用最简单的语言,最简单的代码让人学习设计模式(最起码是我) 说明: 本文的所有内容都是基于...

芝麻开门
04/19
0
0
JavaScript设计模式总结

之前看过《JavaScript设计模式与开发实践》这本书,对书中的设计模式和一些相关案例也有了一定的了解,同时把这些设计模式的应用对应在在一些其他的项目中,进行了一些整理,如下仅供参考: ...

jefferyE
03/26
0
0
(目录)设计模式(可复用面向对象软件的基础)

本系列“设计模式”博客使用Golang语言实现算法。所谓算法是指解决一个问题的步骤,个人觉得不在于语言。小弟只是最近学习Golang,所以顺带熟练一下语法知识,别无它意。 本系列博客主要介绍...

chapin
2015/01/13
0
0
设计模式初步学习笔记(单例模式)

关于设计模式,很久以前通过在网上看了一些资料关于讲设计模式的(推荐大话设计模式),虽说都似乎看懂了,但每次在需要用到相关设计模式的时候总是想不起来,主要对每种设计模式使用场景没研...

lxsh_wyan
04/29
0
0

没有更多内容

加载失败,请刷新页面

加载更多

OpenCv + ffmpeg + rtmp 实现摄像头采集数据直播功能

采用OpenCv获取图像数据,通过ffmpeg推流给rtmp服务器 OpenCV获取的图像数据为BGR格式,需要转换成YUV格式,再将其编码为h264格式,通过ffmpeg推流 头文件 extern "C"{#include <libavco...

cloudjx
30分钟前
1
0
服务器yum源更新为阿里云yum源

1 备份下原来的yum源 cd /etc/yum.repos.d/ mv CentOS-Base.repo CentOS-Base.repo_bak 1 2 3 2 获取阿里云yum源 wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/re......

Mr_Tea伯奕
38分钟前
0
0
CLEARTEXT communication to xxx not permitted by network security policy

Android P http网络请求不通,报出异常:java.net.UnknownServiceException: CLEARTEXT communication to xxxx not permitted by network security policy Google表示,为保证用户数据和设备......

醉雨
52分钟前
3
0
开发函数计算的正确姿势 —— 移植 next.js 服务端渲染框架

首先介绍下在本文出现的几个比较重要的概念: 函数计算(Function Compute): 函数计算是一个事件驱动的服务,通过函数计算,用户无需管理服务器等运行情况,只需编写代码并上传。函数计算准...

阿里云云栖社区
今天
1
0
Windows获取其他进程中Edit控件的内容

最近做的MFC项目中,有个获取其他进程中Edit控件内容的需求,本来以为是个很简单的问题,但是来来回回折腾了不少时间,发博记录一下。   刚开始拿到这个问题,很自然的就想到GetDlgItemTex...

WinkJie
今天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部