C#设计模式——观察者模式

原文链接:
https://www.cnblogs.com/zhili/p/ObserverPattern.html

1. 什么是观察者模式
在软件构建过程中,需要为某些对象建立一种“通知依赖关系”,即一个对象的状态发生改变,所有的依赖对象都要得到通知(比如微信订阅号,订阅号更新内容,会通知所有的订阅者)
观察者模式:
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新

2. 观察者模式的结构
结构图:
在这里插入图片描述
抽象主题角色(Subject):抽象主题把所有观察者对象的引用保存在一个列表中,并提供增加和删除观察者对象的操作,抽象主题角色又叫抽象被观察者角色,一般由抽象类或接口实现。
抽象观察者角色(Observe):为所有具体观察者定义一个接口,在得到主题通知时更新自己,一般由抽象类和接口实现
具体主题角色(Concrete Subject):实现抽象主题接口,具体主题角色又叫做具体被观察者角色
具体观察者角色(Concrete Subject):实现抽象观察者角色所要求的接口,以便使自身状态与主题的状态相协调。

3. 观察者模式的应用

  • 当一个抽象模型有两个方面,一个依赖于另一个方面的情况下。将这二者封装在独立的对象中以使它们可以各自独立地改变和复用
  • 当对一个对象的改变需要同时改变其他对象,而又不知道具体有多少对象有待改变的情况下
  • 当一个对象必须通知其他对象,而又不能假定其他对象是谁的情况下

4. 观察者模式的优缺点
优点:
• 观察者模式实现了表示层和数据逻辑层的分离,并定义了稳定的更新消息传递机制,并抽象了更新接口,使得可以有各种各样不同的表示层,即观察者。
• 观察者模式在被观察者和观察者之间建立了一个抽象的耦合,被观察者并不知道任何一个具体的观察者,只是保存着抽象观察者的列表,每个具体观察者都符合一个抽象观察者的接口。
• 观察者模式支持广播通信。被观察者会向所有的注册过的观察者发出通知。
缺点:
• 如果一个被观察者有很多直接和间接的观察者时,将所有的观察者都通知到会花费很多时间。
• 虽然观察者模式可以随时使观察者知道所观察的对象发送了变化,但是观察者模式没有相应的机制使观察者知道所观察的对象是怎样发生变化的。
• 如果在被观察者之间有循环依赖的话,被观察者会触发它们之间进行循环调用,导致系统崩溃,在使用观察者模式应特别注意这点。

5. 观察模式的实现

class Program
    {
        //客户端测试
        static void Main(string[] args) {
            OfficialAccounts oa = new OfficialAccountsIT("IT", "程序员行业最新动态");
            //添加订阅者
            oa.AddObserver(new Subscriber("行走的荷尔蒙"));
            oa.AddObserver(new Subscriber("蒲公英"));
            oa.Update();
            Console.ReadKey();
        }
    }
    //订阅者接口
    public interface IObserver
    {
        void Show(OfficialAccounts oa);
    }
    //具体订阅者类
    public class Subscriber:IObserver
    {
        //订阅者名字
        public string Name { get; set; }
        public Subscriber(string name) {
            this.Name = name;
        }
        //显示接收到公众号的信息
        public void Show(OfficialAccounts oa) {
            Console.WriteLine("订阅者{0}收到了公众号Style{1},Description{2}的信息",Name,oa.Category, oa.Description );
        }
    }

    //公众号抽象类
    public abstract class OfficialAccounts 
    {
        private List<IObserver> observers  = new List<IObserver>();

        //公众号类别
        public string Category { get; set; }
        //公众号简介
        public string Description { get; set; }

        public OfficialAccounts(string category, string description) {
            this.Category = category;
            this.Description = description;
        }
        //订阅者开始关注
        public void AddObserver(IObserver ob) {
            observers.Add(ob);
        }
        //订阅者取消关注
        public void RemoveObserver(IObserver ob) {
            observers.Remove (ob);
        }

        //向所有订阅者发送更新内容
        public void Update (){
            foreach (IObserver ob in observers) {
                if(ob != null) {
                    ob.Show(this);
                }
            }
        }
    }

    public class OfficialAccountsIT:OfficialAccounts
    {
        public OfficialAccountsIT(string category,string description) : base(category, description) {

        }
    }

6 .NET 中观察者模式的应用(使用委托实现观察者模式)

//委托充当订阅者接口
    public delegate void ObserverEventHandler(object sender);
    class Program
    {
        //客户端测试
        static void Main(string[] args) {
            OfficialAccounts oa = new OfficialAccountsIT("IT", "程序员行业最新动态");
            Subscriber sb1 = new Subscriber("行走的荷尔蒙");
            Subscriber sb2 = new Subscriber("蒲公英");
            //添加订阅者
            oa.AddObserver(sb1.Show);
            oa.AddObserver(sb2.Show);
            oa.Update();
            Console.ReadKey();
        }
    }

    //具体订阅者类
    public class Subscriber
    {
        //订阅者名字
        public string Name { get; set; }
        public Subscriber(string name) {
            this.Name = name;
        }
        //显示接收到公众号的信息
        public void Show(object sender) {
            OfficialAccounts oa = sender as OfficialAccounts;
            if(oa != null) {
                Console.WriteLine("订阅者{0}收到了公众号Style{1},Description{2}的信息", Name, oa.Category, oa.Description);
            }
        }
    }

    //公众号抽象类
    public abstract class OfficialAccounts 
    {
        private ObserverEventHandler eventHandler;

        //公众号类别
        public string Category { get; set; }
        //公众号简介
        public string Description { get; set; }

        public OfficialAccounts(string category, string description) {
            this.Category = category;
            this.Description = description;
        }
        //订阅者开始关注
        public void AddObserver(ObserverEventHandler oh) {
            eventHandler += oh;
        }
        //订阅者取消关注
        public void RemoveObserver(ObserverEventHandler oh) {
            eventHandler -= oh;
        }

        //向所有订阅者发送更新内容
        public void Update (){
            if(eventHandler != null) {
                eventHandler(this);
            }
        }
    }

    public class OfficialAccountsIT:OfficialAccounts
    {
        public OfficialAccountsIT(string category,string description) : base(category, description) {

        }
    }
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
原型模式是一种创建型设计模式,其提供了一种复制已有对象的方法来生成新对象的能力,而不必通过实例化的方式来创建对象。原型模式是通过克隆(浅复制或深复制)已有对象来创建新对象的,从而可以避免对象创建时的复杂过程。 在C#中,可以通过实现ICloneable接口来实现原型模式。ICloneable接口定义了Clone方法,该方法用于复制当前对象并返回一个新对象。需要注意的是,Clone方法返回的是Object类型,需要进行强制类型转换才能得到复制后的对象。 以下是一个简单的示例代码: ```csharp public class Person : ICloneable { public string Name { get; set; } public int Age { get; set; } public object Clone() { return MemberwiseClone(); } } // 使用示例 var person1 = new Person { Name = "Tom", Age = 20 }; var person2 = (Person)person1.Clone(); person2.Name = "Jerry"; Console.WriteLine(person1.Name); // 输出 "Tom" Console.WriteLine(person2.Name); // 输出 "Jerry" ``` 在上面的示例代码中,实现了一个Person类,并实现了ICloneable接口中的Clone方法来实现原型模式。复制对象时,使用MemberwiseClone方法进行浅复制,即只复制值类型的字段和引用类型字段的引用,而不复制引用类型字段所引用的对象。在使用示例中,首先创建一个Person对象person1,然后通过Clone方法复制一个新的对象person2,修改person2的Name属性后,输出person1和person2的Name属性,可以看到person1的Name属性并没有改变,说明person2是一个全新的对象。 需要注意的是,如果要实现深复制,即复制引用类型字段所引用的对象,需要在Clone方法中手动将引用类型字段复制一份。另外,使用原型模式时,需要注意复制后的对象和原对象之间的关系,如果复制后的对象修改了原对象的状态,可能会对系统产生意想不到的影响。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值