A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 严明 初级黑马   /  2012-6-26 08:24  /  2304 人查看  /  4 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 严明 于 2012-6-26 08:58 编辑

最近在看一些有关模式的文章,在此将一些学习心得与大家共享一下,并用白话文解释一下这些看似高深莫的东西,先来上一个观察者模式.


1,        观察者(具体执行操作的对象,有多个)
2,        被观察者(顾名思义是被观察的对象,如果该对象发生某些变化则通知观察者执行对应的操)

为了便于理解,首先我举一个现实生活中的例子:
    A 每天要吃饭, 娱乐.....,
而B 要监视A 的一举一动,获得A 的所有活动,话不多说,代码解释:

先定义一个接口 I_A
public interface  I_A//A是被观察者,先将这类人抽象成一个接口
{
    public void havaBreakfast();//A 要 吃饭
   
    public void haveFun();//A要娱乐
}


再定义一个具体的被观察者 A 来实现 I_A

public class A implements I_A //A 是一个被观察者,每天都有两个要执行的动作:havaBreadfast,haveFun
{
    private I_B b=new B();   //将B声明出来,  这就成了一种聚集方式的被观察者.

    @Override
    public void havaBreakfast()
    {
         System.out.println("A 开始吃饭了......");
         //马上就通知B
         this.b.update("A 现在就在吃饭了.........");
        
    }
    @Override
    public void haveFun()
    {
        System.out.println("A 开始娱乐了......");
         //马上就通知B
         this.b.update("A 现在就在娱乐了.........");
        
    }

}

观察者模式当然少不了观察者

public interface I_B // B 这种人是一个观察者,A 的所有行动 B都能准时知道
{
   public void update(String context);// 接收间碟传入的参数,并采取行动
}

再定义一个具体的观察者 B 来实现 I_B

public class B implements I_B
{

    public void update(String context)
    {
        System.out.println("观察到 A 开始有活动了:"+context);
        
    }

}



最后模拟一个场景来测试

public class Client //设置 一个测试场景,看B 能否及时的观察到A 的行动 ,这也是一种聚集方式的场景类.
{
    public static void main(String[] args){
        
        A a = new A();//定义出A
        
        //然后来看看A 到底在干什么?
        a.havaBreakfast();//A 吃饭了
        a.haveFun();//A 娱乐了
              
    }

}



有人可能会想,应该定义3个类来模拟,一个被观察者A  一个观察者B  还有 一个传递消息的间谍类Spy, 创建一个后台线程一直处于运行状态,当发现A 有所行动就马上触发事件报告给B, B 再触发事件update(),
如果,你这样想了的话,那么可以准确的告诉你:你的思维还是停留在完全面向过程的阶段, 这样写出来的程序就不是面向对象的了,
最糟糕的是: 如果创建一个后台线程一直处于运行状态,就必须用一个死循环while(true){  },那么用到项目中的话,必须非常大的硬件投入,还不让别的程序运行了?


观察者将自己注册到被观察者的容器中时,被观察者不应该过问观察者的具体类型,而是应该使用观察者的接口。这样的优点是:假定程序中还有别的观察者,那么只要这个观察者也是相同的接口实现即可。一个被观察者可以对应多个观察者,当被观察者发生变化的时候,他可以将消息一一通知给所有的观察者。基于接口,而不是具体的实现——这一点为程序提供了更大的灵活性。



并且我上面的例子的代码是有问题的:
问题1:在class A 中的 private I_B b=new B(); 只有B 一个人能观察到A的行动,那么其他人要监视A的行动怎么办呢?  
问题2:B只观察A的吃饭,娱乐吗? A还有政治倾向  感情生活 情绪变化  恋爱倾向  .........那么多一系列活动都要通知 B ,这如何是好?
在class A中定义 那么那么多的方法来实现吗?  不,这和开闭原则是严重相违背的

说实话,在下还没有研究透彻,若有高手看到,望指点一下,若你觉得对你有帮助,请赞一个,think you!




评分

参与人数 1黑马币 +20 收起 理由
黄奕豪 + 20 赞一个!

查看全部评分

4 个回复

倒序浏览
等了半天,  没人回复啊,   雁过不留痕者,  不厚道!{:soso_e118:}
回复 使用道具 举报
等了半天,  没人回复啊,   雁过不留痕者,  不厚道!{:soso_e118:}
回复 使用道具 举报
我来厚道一把;分享了;谢谢;
回复 使用道具 举报
我暂时不去看你的代码,你先看看我讲的思路你是否能看懂:
1.被观察者和观察者永远是在一个线程里。
2.之所以观察者察觉到被观察者变化了,是因为被观察者主动告诉他了。
3.被观察者只有一个,观察者可以有多个。
这几点我认为是比较重要的,被观察者在内部有一个通知观察者的方法。
基于上面我们可以想到,被观察者内部一定有三个方法:添加观察者、删除观察者、还有通知观察者。
而观察者内部也一定有个方法:响应被观察者请求。
而观察者都会用一个list的形式存放在被观察者的内部。当你需要通知观察者时你只需要遍历这个集合里的所有观察者,挨个通知他就可以了。
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马