悄然无声的 Blog
不是我不明白,这世界变化快!

观察者模式 Observer Pattern — 三国演义之超级间谍战 — 美女貂蝉的故事

说明:我也是初学者,希望大家能提出宝贵意见。另外转载请注明作者左光和出处博客园,毕竟花费了很长时间才完成。

前言:

在网上搜索一下 MVC 模式,大部分都是和 StrutsSpring 这些东东有关的,好像一说到MVC 模式,就必须和框架有关似的,费了半天劲仍然是晕晕乎乎,好在其中的观察者模式比较好理解,这两天正好又在听袁阔成的评书《三国演义》,于是就结合三国故事和观察者模式写下这一篇《三国演义之超级间谍战 — 美女貂蝉的故事》,希望大家多给一点指教。

点击浏览更多的“说故事、学模式”系列

情节:

这一次讲的故事情节很简单,但是充满了谋略和斗争。大体意思就是三国初期,曹刘孙三家在徐州联手消灭了吕布,但是自己也伤了元气。而此时袁术得了传国玉玺,在淮南称帝,兵精将广,图谋不轨,对三家威胁都很大。于是曹刘孙三家在一起开了个会,决定派遣一名超级间谍打入到袁术身旁,监视他的一举一动,这样的话一旦袁术想干什么坏事,他们就可以立刻知道并做出相应的调整,知己知彼百战百胜嘛。

计是好计,问题是派谁去当这个超级间谍呢?正当大家愁眉苦脸的时候,美女貂蝉自告奋勇,想当年董卓那么厉害都让我灭了,何况一个小小的袁术呢?大家一听,说的有理,于是就把貂蝉献给了袁术当了妃子。另外三家还各派出一名小奸细常住在淮南城内,他们的任务是当联络员,貂蝉有什么情报总不能自己曹刘孙三家挨个跑着送吧?直接丢给各国联络员,然后让他们通知各自的主公就 OK 了!而三家只要一接到各自奸细的通知,就会立即做出反应。

还有一个小插曲,袁术虽然收下了貂蝉,但是对她看管很严,大大方方地把情报送出去不太可能,逼不得以,貂蝉自己设计了一套密码来传递情报,虽然加密方法没有公开,但是她想总有人可以破解了吧?没错,对诸葛亮来说就是小菜一碟,从此袁术穿什么内裤曹刘孙三家都知道得清清楚楚。

分析:

下面我们用 观察者模式  来分析一下上面这个故事

1、美女貂蝉:貂蝉在观察者模式中叫做被观察者(Subject),主要任务是独立的管理后台数据和业务逻辑,同时尽可能不受前台客户端界面变化的影响。当然,还要负责登记或者注销各个观察者。

在这个故事里,貂蝉仅仅维护了一个数据 ,就是情报 —  私有变量 info ;另外还拥有一个业务逻辑,是用来加密 info 的方法 Reverse(string str) 。每次得到新的情报,她就会先加密,然后立刻找到在自己这登记过的联络员,让这些联络员通知自己的主公应变。

情报一旦发送出去, 貂蝉的任务就算完成了,具体曹刘孙三家怎么应对,是打是降还是另有其他方法,那是三家自己的事情,和她貂蝉就没什么关系了。

2、曹刘孙三家:曹刘孙三家在观察者模式里叫做观察者,主要任务就是从界面上用“各种方式”即时的反映出 被观察者,所谓“各种方式”就是说用字符、图形、声音都可以表示同样数据,外在表现不同而已,本质都是一些数据。所谓“即时”,就是说只要 被观察者 发生变化, 观察者 也会立刻跟着变化,用行话应该叫做刷新 Update吧。

在这个故事里,我们可以看到运行结果中,每次貂蝉有什么新的情报,三家都会在屏幕上显示出来,虽然很简单,但 他们确实是用各自不同的方式表示了同样的数据

下面来看看代码是怎么描述这个故事的吧。

类文件 Observer.cs

using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;

namespace ObserverPattern
{
    
//这个类描述 美女间谍貂蝉,她是一个 被观察者 或者说是 消息发布者
    
//她的任务只是负责发布消息,观察者 得到消息后怎么处理就不是她操心的事情了
    public class Diao_Model
    
{
        ArrayList spyList 
= new ArrayList();
        
string info;

        
//构造函数
        public Diao_Model()
        
{
            Console.WriteLine(
"貂蝉:每次危难关头,还得看小女子貂蝉出马!\n");
        }


        
//登记观察者
        public void RegisterObserver(Observer o)
        
{
            Console.WriteLine(
"{0}的奸细来了..",o.Name);
            spyList.Add(o);
        }


        
//移除观察者
        public void RemoveObserver(Observer o)
        
{
            Console.WriteLine(
"{0}不想干了,把奸细撤走了..", o.Name);
            spyList.Remove(o);
        }


        
//设置和获得情报
        public string Info
        
{
            
get
            
{
                
return info;
            }

            
set
            
{
                Console.WriteLine(
"貂蝉:得到情报‘{0}’!\n", value);
                info 
= Reverse(value);
                Notify();
//每次得到情报后就立刻通知
            }

        }


        
//情报不加密送不出去呀,实际上就是颠倒顺序
        
//这是貂蝉自己的业务逻辑,外部是不知道的
        private string Reverse(string str)
        
{
            
string temp = null;
            
for (int i = str.Length - 1; i >= 0; i--)
                temp 
= temp + str[i];
            Console.WriteLine(
"情报已经被加密为:‘{0}’,这是内部逻辑,别人都不知道\n", temp);
            
return temp;
        }


        
// 当数据改变时,通知各个Observer,做出相应的反应
        private void Notify()
        
{
            Console.WriteLine(
"貂蝉:情报‘{0}’已经通过奸细送往各国,他们怎么办我就不管了.\n", info);
            
foreach (Object spy in spyList)
            
{
                Observer o 
= (Observer)spy;
                o.Update(
this);
            }

        }

    }
 

    
//==========================================================================

    
//抽象观察者
    public interface Observer
    
{
        
string Name get;}
        
void Update(Diao_Model model);
    }


    
//曹操 观察者 之一
    public class Cao_View : Observer
    
{
        
string name = "曹操";

        
public string Name
        
{
            
get return name; }
        }


        
public void Update(Diao_Model model)
        
{
            Console.WriteLine(
"曹孟德:‘{0}’是什么意思?貂蝉小妞到底想不想干了?", model.Info);
            Console.WriteLine(
"曹孟德:立刻进入一等战备,随时迎敌!\n");
        }

    }


    
//刘备 观察者 之一,诸葛亮竟然会破解密码!
    public class Liu_View : Observer
    
{
        
string name = "刘备";

        
public string Name
        
{
            
get return name; }
        }


        
public void Update(Diao_Model model)
        
{
            Console.WriteLine(
"刘玄德:这密码是什么意思呀?快快请诸葛先生来.");
            Console.WriteLine(
"诸葛亮:主公勿慌,密码已经破译了,貂蝉说‘{0}’\n", Reverse(model.Info));
        }


        
private string Reverse(string str)
        
{
            
string temp = null;
            
for (int i = str.Length - 1; i >= 0; i--)
                temp 
= temp + str[i];
            
return temp;
        }

    }


    
//孙策 观察者 之一
    public class Sun_View : Observer
    
{
        
string name = "孙策";

        
public string Name
        
{
            
get return name; }
        }


        
public void Update(Diao_Model model)
        
{
            Console.WriteLine(
"孙策:‘{0}’??貂蝉发一堆乱码做甚?!", model.Info);
            Console.WriteLine(
"孙策:不管怎样,还是准备一下好,擂鼓升帐!!!");
        }

    }
  
}

客户端 Client.cs

using System;
using System.Collections.Generic;
using System.Text;

namespace ObserverPattern
{
    
class Program
    
{
        
static void Main(string[] args)
        
{
            Console.WriteLine(
"故事开始了..\n");

            
//创建 被观察者 貂蝉
            Diao_Model diaochan = new Diao_Model();

            
//创建各国奸细
            Cao_View cao = new Cao_View();
            Liu_View liu 
= new Liu_View();
            Sun_View sun 
= new Sun_View();

            
//貂蝉开始联络各国奸细并登记造册
            Console.WriteLine("貂蝉开始联络各国奸细\n");
            diaochan.RegisterObserver(cao);
            diaochan.RegisterObserver(liu);
            diaochan.RegisterObserver(sun);
            Console.WriteLine();

            
//貂蝉得到一条重要信息
            diaochan.Info = "袁术得了重感冒";
            Console.WriteLine();

            
//孙策不想干了,他的奸细被貂蝉注销了
            diaochan.RemoveObserver(sun);
            Console.WriteLine();

            
//貂蝉又得到一条重要信息
            diaochan.Info = "袁术有骑兵10万";
            Console.WriteLine();
            
            Console.Read();
        }

    }

}

运行效果如下:

点击浏览更多的“说故事、学模式”系列

 

posted on 2005-09-21 21:28  左洸  阅读(2426)  评论(14编辑  收藏  举报