前言:

在网上搜索一下 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();
        }

    }

}

运行效果如下:


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理


Copyright © fred