为集合类型封装观察者模式

本文是《设计模式_基于C#的工程化实现及扩展》的读书笔记,部分内容直接引用该书。

 

以下代码展示的是如何为集合类型封装观察者模式。这样当集合元素增加的时候,通过我们自定义集合类的内部委托,就会通知到每个感兴趣的观察者。回想观察者模式的实现原理。观察者模式就是在被观察者SubjectClass里面记录一个观察者感性趣的消息(在本例中是ObserverableDictionary类中的DictionaryEventArgs),然后通过委托通知多个对象(通知机制的原理其实是通过后期将与SubjectClass内部委托相同方法签名的函数绑定在委托上,这样当委托被调用的时候,绑定在这个委托上的方法一并被调用,实现通知多个观察者的现象)。本本例中,ObserverableDictionary类通过继承接口获得一个封装好的委托属性,通过继承Dictionary类获得字典类型实现的缓冲特性。有了相应的委托和缓冲,在最后面ObserverableDictionary类通过重写父类Dictionary类的Add的方法,在Add方法里面调用类内部定义的一个委托,实现通知多个观察者的效果、

using System;
using System.Collections.Generic;
namespace
MarvellousWorks.PracticalPattern.ObserverPattern.ObserverCollection.Simple
{
    /// <summary>
    /// 用于保存集合操作中操作条目信息的时间参数
    /// </summary>
    /// <typeparam name="TKey"></typeparam>
    /// <typeparam name="TValue"></typeparam>
    public class DictionaryEventArgs<TKey, TValue> : EventArgs
    {
     /**
      该类后面作为NewItemAdded 委托的参数。
     **/

        private TKey key;
        private TValue value;

        public DictionaryEventArgs(TKey key, TValue value)
        {
            this.key = key;
            this.value = value;
        }

        public TKey Key { get { return key; } }
        public TValue Value { get { return value; } }
    }

    /// <summary>
    /// 具有操作事件的IDictionary<TKey, TValue>接口
    /// </summary>
    /// <typeparam name="TKey"></typeparam>
    /// <typeparam name="TValue"></typeparam>
    public interface IObserverableDictionary<TKey, TValue> :
        IDictionary<TKey, TValue>
    {
        //设置一个对外通知的接口
        EventHandler<DictionaryEventArgs<TKey, TValue>>  NewItemAdded { get; set;}
    }

    /// <summary>
    /// 一种比较简单的实现方式
    /// </summary>
    /// <typeparam name="TKey"></typeparam>
    /// <typeparam name="TValue"></typeparam>
    public class ObserverableDictionary<TKey, TValue> :
        Dictionary<TKey, TValue>, IObserverableDictionary<TKey, TValue>
    {
       //该类通过继承Dictionary,获得Dictionary的属性和方法
       //通过继承IObserverableDictionary,获得对外通知的委托
        protected EventHandler<DictionaryEventArgs<TKey, TValue>>  newItemAdded;
        public EventHandler<DictionaryEventArgs<TKey, TValue>>  NewItemAdded
        {
            get { return newItemAdded; }
            set { newItemAdded = value; }
        }

        /// <summary>
        /// 为既有操作增加事件
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public new void Add(TKey key, TValue value)//使用new显示说明覆盖父类的方法
        {

            base.Add(key, value);//通过调用父类的方法,将key和value写入Dictionnary缓冲
            if (NewItemAdded != null)
                NewItemAdded(this, new DictionaryEventArgs<TKey, TValue>(key, value));//当集合元素增加时,通过委托实现对外通知
        }
    }
}

最后附上单元测试

 

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Diagnostics;
 4 using Microsoft.VisualStudio.TestTools.UnitTesting;
 5 using MarvellousWorks.PracticalPattern.ObserverPattern.ObserverCollection.Simple;
 6 namespace MarvellousWorks.PracticalPattern.ObserverPattern.Test.ObserverCollection.Simple
 7 {
 8     [TestClass]
 9     public class TestObserver
10     {
11         string key = "hello";
12         string value = "world";
13
14         public void Validate(object sender, DictionaryEventArgs<string, string> args)
15         {
16             Assert.IsNotNull(sender);
17             Type expectedType = typeof(ObserverableDictionary<string, string>);
18             Assert.AreEqual<Type>(expectedType, sender.GetType());
19             Assert.IsNotNull(args);
20             expectedType = typeof(DictionaryEventArgs<string, string>);
21             Assert.AreEqual<Type>(expectedType, args.GetType());
22             Assert.AreEqual<string>(key, args.Key);
23             Assert.AreEqual<string>(value, args.Value);
24             Trace.WriteLine(args.Key + "  " + args.Value);
25         }
26
27         [TestMethod]
28         public void Test()
29         {
30             IObserverableDictionary<string, string> dictionary =
31                 new ObserverableDictionary<string, string>();
32             dictionary.NewItemAdded += this.Validate;
33             dictionary.Add(key, value);
34         }
35     }
36 }

 

作者:kissazi2 
出处:http://www.cnblogs.com/kissazi2/ 
本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

转载:http://www.cnblogs.com/kissazi2/archive/2013/04/21/3033849.html

时间: 2024-10-04 01:24:34

为集合类型封装观察者模式的相关文章

C# 3.0新特性初步研究 Part4:使用集合类型初始化器

集合 集合类型初始化器(Collection Initializers) 想看一段"奇怪"的代码: 1class Program 2    { 3        static void Main(string[] args) 4        { 5            var a = new Point { x = 10, y = 13 }; 6            var b = new Point { x = 33, y = 66 }; 7 8            var

.net集合类型的接口说明与使用

本文介绍了.net集合类型的接口说明与使用,内容比较简单,主要是为了理清思路以及明确集合类型作为参数和返回值时的使用规范,关于集合类型的更多讨论也可以参看:认识.NET的集合. NET类库提供了丰富的集合数据类型,光System.Collections 命名空间就提供了:列表.队列.位数组.哈希表和字典等多种集合类型.以该命名空间下的集合类型来讲,大体可以分为两类:列表,与字典.前者按照顺序访问集合中的数据,后者提供了键值对的访问方式. 本文主要介绍了列表类型的接口说明和使用上的建议,不涉及.n

Swift语法专题五——集合类型

Swift讲解专题五--集合类型 一.引言         Swift中提供了3种集合类型,Array数据类型,Set集合类型,Dictionary字典类型.Array用于存放一组有序的数据,数据角标从0开始一次递增:Set用于存放一组无序的数据,数据不可以重复:Dictionary也用于存放一组无序的数据,只是其是按照键值对的方式存储,键值必须唯一.这里借用官方文档中的一张图来表示3种集合类型的特点: 二.Array类型         Array通常也被称为数组,Swift是一种类型安全语言

springMVC4(12)复杂对象和集合类型入参绑定

1. 复杂对象参数绑定 对于普通的对象参数绑定,我们只需要对象成员变量名与请求参数名一一对应即可完成绑定. 而求对于组合对象,我们可以使用级联的方式来绑定方法参数.见下面实例: 我们先定义两个POJO类:User,Article其中Atricle是User的成员属性: public class Article { private Integer id; private String title; private String content; //忽略get和set方法 } package co

Python回顾与整理5:映像和集合类型

0.说明         依然是按照前面介绍的几种序列类型的思路来总结字映像类型和集合类型,即先做一个介绍,再讨论可用操作符.工厂函数.内建函数和方法. 1.映射类型:字典         映射类型被称做哈希表,而Python中的字典对象就是哈希类型,即它是按照这样的方式来存储数据:(哈希表的算法)是获取键,对键执行一个叫做哈希函数的操作,并根据计算的结果,选择在数据结构的某个地址中来存储对象的值.任何一个值存储的地址取决于它的键,正因为这种随意性,哈希表中的值是没有顺序的,所以Python中的

Dart入门—集合类型

Dart入门-集合类型 Dart核心库提供了List(列表).Map(映射).Set(集)三种集合类型 列表(List) 固定长度的列表,一旦定义就无法改变长度 List<int> fixedLengthList = new List(5); fixedLengthList[0] = 87; print(fixedLengthList); print(fixedLengthList[0]); 可改变长度的列表,可以根据需要改变长度 List<int> growableList =

15天玩转redis —— 第六篇 有序集合类型

今天我们说一下Redis中最后一个数据类型 "有序集合类型",回首之前学过的几个数据结构,不知道你会不会由衷感叹,开源的世界真好,写这 些代码的好心人真的要一生平安哈,不管我们想没想的到的东西,在这个世界上都已经存在着,曾几何时,我们想把所有数据按照数据结构模式组成 后灌输到内存中,然而为了达到内存共享的方式,不得不将这块内存包装成wcf单独部署,同时还要考虑怎么序列化,何时序列互的问题,烦心事太多 太多...后来才知道有redis这么个吊毛玩意,能把高级的,低级的数据结构单独包装到一

java中基本类型封装对象所占内存的大小(转)

这是一个程序,java中没有现成的sizeof的实现,原因主要是java中的基本数据类型的大小都是固定的,所以看上去没有必要用sizeof这个关键字. 实现的想法是这样的:java.lang.Runtime类中有一些简单的能涉及到内存管理的函数: Every Java application has a single instance of class Runtime that allows the application to interface with the environment in

[Google Guava] 2.2-新集合类型

原文链接 译文链接 译者:沈义扬,校对:丁一 Guava引入了很多JDK没有的.但我们发现明显有用的新集合类型.这些新类型是为了和JDK集合框架共存,而没有往JDK集合抽象中硬塞其他概念.作为一般规则,Guava集合非常精准地遵循了JDK接口契约. Multiset 统计一个词在文档中出现了多少次,传统的做法是这样的: Map<String, Integer> counts = new HashMap<String, Integer>(); for (String word : w