观察者模式

上一篇 / 下一篇  2009-09-15 10:39:46 / 个人分类:.NET设计模式

意图

定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。[GOF《设计模式》]

下面以自动化测试为例来说明观察者模式的含义:

做过自动化测试的都知道一个自动化的测试case主要分三个部分:Init-在一个case开始之前做一些初始化的工作,想读取测试数据阿,打开应用程序之类的, TestMethod-测试步骤都在这个测试方法中,最后一个是CleanUp-在一个case结束后作一些清理的工作,像关闭数据库,写日志之类的,当然可能不同的人名字叫的不一样,不过大体都是分这三部的。

首先,我们有一个TestBase类:

    public abstract class TestBase
    {
        protected abstract void Init();
        protected abstract void TestMethod();
        protected abstract void CleanUp();

        public void Run()
        {
            Init();
            TestMethod();
            CleanUp();
        }
    }

可以看出,基类TestCase的Run()方法其实就是跑一个case的入口,这里当然还用刀了模板方法模式,不过我们可以暂时不用管它。我们只要知道,在一个自动化case运行的时候(即Run方法被调用的时候),必须经过上述的三个阶段。

现在我们想,在case开始的时候,我们可能会写一些记录,或告诉用户case已经开始了,在case运行过程中,我们可能会收集一些数据,在case结束的时候,我们可能会将最终的结果写入XML文件,或写入一个case结果管理工具中。这些其实都是一种“通知”,即在不同的阶段通知不同的对象,即便同一个阶段,在不同的case或不同的运行时间,我们也能通知不同的对象。这就用到了观察者模式。在这个例子中,其实就是在调用Init()的时候,我们要在其中作出CaseInit的通知,在调用TestMethod的时候我们要做出CaseRun的通知,在调用CleanUp()的时候要做出CaseCleanUp的通知,因为通知其实就是要调用一个函数,所以,观察者模式其实就是要在我们发通知的地方放一个“函数的占位符”。因为有三种不同类型的通知,所以我们有下面三种类:

    public interface InitObserver
    {
        void CaseStart(EventArgs arg);
    }

    public interface TestMethodObserver
    {
        void CaseRun(EventArgs arg);
    }

    public interface CleanUpObserver
    {
        void CaseCleanUp(EventArgs arg);
    }

上面的EventArgs类型的参数是我临时用的,可以根据需要改成其他类型的参数来更好的获得需要的数据。

然后修改TestBase来放我们所谓的“占位符”:

    public abstract class TestBase
    {
        public List<InitObserver> initObserverList = new List<InitObserver>();
        public List<TestMethodObserver> testMethodObserverList = new List<TestMethodObserver>();
        public List<CleanUpObserver> cleanUpObserverList = new List<CleanUpObserver>();

        private void Init()
        {
            foreach (InitObserver elem in initObserverList)
                elem.CaseStart(new EventArgs());

            TestInitialize();
        }
        private void TestStep()
        {
            TestMethod();

            foreach (TestMethodObserver elem in testMethodObserverList)
                elem.CaseRun(new EventArgs());
        }

        private void CleanUp()
        {
            foreach (CleanUpObserver elem in cleanUpObserverList)
                elem.CaseCleanUp(new EventArgs());

            TestCleanUp();
        }

        protected abstract void TestInitialize();
        protected abstract void TestMethod();
        protected abstract void TestCleanUp();

        public void Run()
        {
            Init();
            TestStep();
            CleanUp();
        }
    }

这样,在case开始之前,只要初始化好initObserverList,testMethodObserverList cleanUpObserverList,在相应的阶段就会对那些对象做出相应的通知。

在.NET的环境中,观察者模式有了更简单的做法:

首先将 InitObserver,TestMethodObserver,public interface CleanUpObserver这三个接口去掉,

然后定义三个代理:

    public delegate void initObserverHandler(EventArgs arg);
    public delegate void testMethodObserverHandler(EventArgs arg);
    public delegate void cleanUpObserverHandler(EventArgs arg);

修改TestBase:

    public abstract class TestBase
    {
        initObserverHandler initObserver;
        testMethodObserverHandler testMethodObserver;
        cleanUpObserverHandler cleanUpObserver;

        private void Init()
        {
            initObserver(new EventArgs());

            TestInitialize();
        }
        private void TestStep()
        {
            TestMethod();

            testMethodObserver(new EventArgs());
        }

        private void CleanUp()
        {
            cleanUpObserver(new EventArgs());

            TestCleanUp();
        }

        protected abstract void TestInitialize();
        protected abstract void TestMethod();
        protected abstract void TestCleanUp();

        public void Run()
        {
            Init();
            TestStep();
            CleanUp();
        }
    }


TAG:

 

评分:0

我来说两句

Open Toolbar