• 设计模式观察者模式


    定义:

    定义了对象之间一对多的关系,这样一来,当一个对象发生变化时,他的所有依赖者都会收到通知,并自动更新.

    关键词:

    observer : 观察者

    subject : 主题

    concreteObserver: 具体观察者

    结构图:

    image

    应用场景:

    当一个对象的状态变化时,需要通知其他多个对象进行同步更新时,可以使用此模式(如果有且只有一个对象需要更新,就没有必要了)

    当需要动态增加删除需要同步的对象时

    对象仅仅需要将自己的更新通知其他对象,而无需知道其他对象实现细节时.

    优点:

    subject 和 observer是高内聚,低耦合的,他们仅通过接口进行联系

    无需指定具体的observer

    缺点:

    松耦合导致代码之间看起来关系不明显,比较难理解.

    例子:

    日志记录.当发生一个事件或者有状态变化时,需要日志记录下来.要求同时有数据库记录和文件记录.该如何写的?

    通常写法是:

    public class Record
    {
        public void notify()
        {
            DatabaseLog d = new DatabaseLog();
            d.RecordToDataBase();
    
            FileLog f = new FileLog();
            f.RecordToFile();
        }
    }
    
    public class DatabaseLog
    {
        public void RecordToDataBase()
        {
            //TODO
        }
    }
    
    public class FileLog
    {
        public void RecordToFile()
        {
            //TODO
        }
    }

    当有变化时,页面上只需要调用

            Record r = new Record();
            r.notify();

    即可.

    但是:如果要求新增一种记录方式,web记录时,该如何处理呢?

    新增一个WebLog类,然后修改Record类.

    public class Record
    {
        public void notify()
        {
            DatabaseLog d = new DatabaseLog();
            d.RecordToDataBase();
    
            FileLog f = new FileLog();
            f.RecordToFile();
    
            WebLog w = new WebLog();
            w.RecordToWeb();
        }
    }
    
    public class DatabaseLog
    {
        public void RecordToDataBase()
        {
            //TODO
        }
    }
    
    public class FileLog
    {
        public void RecordToFile()
        {
            //TODO
        }
    }
    
    public class WebLog
    {
        public void RecordToWeb()
        {
            //TODO
        }
    }
    于是,我们发现:针对实际编程,每当有新增时,我们都需要添加新的记录类,并且修改Record类.
    仔细观察三种记录方式,其实都是在对所发生的事情那个做记录,只是记录的方式不一样罢了.
    类图:
    image 
    代码:
    public interface ISubject
    {
        void RegisterObserver(IObserver observer);
    
        void RemoveObserver(IObserver observer);
    
        void NotifyObservers();
    }
    
    public class Record : ISubject
    {
        private ArrayList observersList;
    
        public Record()
        {
            observersList = new ArrayList();
        }
    
        public void RegisterObserver(IObserver observer)
        {
            observersList.Add(observer);
        }
    
        public void RemoveObserver(IObserver observer)
        {
            observersList.Remove(observer);
        }
    
        public void NotifyObservers()
        {
            foreach (IObserver observer in observersList)
            {
                observer.Record();
            }
        }
    
        public void SetEvent(int el)
        {
            if (el > 10)
            {
                NotifyObservers();
            }
        }
    }
    
    public interface IObserver
    {
        void Record();
    }
    
    public class DatabaseLog : IObserver
    {
        private ISubject subject;
    
        public DatabaseLog(ISubject subject)
        {
            this.subject = subject;
            subject.RegisterObserver(this);
        }
    
        public void Record()
        {
            //TODO
        }
    }
    
    public class FileLog : IObserver
    {
        private ISubject subject;
    
        public FileLog(ISubject subject)
        {
            this.subject = subject;
            subject.RegisterObserver(this);
        }
    
        public void Record()
        {
            //TODO
        }
    }
    
    public class WebLog : IObserver
    {
        private ISubject subject;
    
        public WebLog(ISubject subject)
        {
            this.subject = subject;
            subject.RegisterObserver(this);
        }
    
        public void Record()
        {
            //TODO
        }
    }
    页面调用:
        protected void Page_Load(object sender, EventArgs e)
        {
            Record r = new Record();
    
            DatabaseLog dbl = new DatabaseLog(r);
            FileLog fl = new FileLog(r);
            WebLog wl = new WebLog(r);
    
            r.SetEvent(100);
        }
    此时,如果需要增加其他的记录方式的话,需要添加一个类实现Iobserver,然后还需要修改客户端页面.
    通过配置文件,我们还可以使客户端做到易插拔.
    <hr/>
    以下来自<<深入浅出设计模式>>
     
    涉及到的设计原则:
    封装变化
        在观察者模式中,会改变的是主题(Subject)的状态,以及观察者(Observer)的数量和具体类型.
    面向接口编程
        观察者和主题都使用接口,观察者使用主题的接口,主题使用观察者的接口.做到了松耦合.
    优先使用对象组合,而不是继承
        观察者模式利用组合讲许多观察者组合进主题,对象之间的这种关系不是通过继承得到的,而是在运行时运用动态的组合生成的.
  • 相关阅读:
    MVC常用跳转页面的方法
    简单工厂模式
    MySQL 查询昨天中午12点到今天中午12点的数据
    Windows安装yarn
    MapStruct
    CSS 3D
    05-序列化器ModelSerializer
    django基础之Django中间件
    04-序列化器Serializer
    03-四大基本模块
  • 原文地址:https://www.cnblogs.com/oneword/p/1447013.html
Copyright © 2020-2023  润新知