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

© 创造命运 中级黑马   /  2014-4-16 10:28  /  1116 人查看  /  4 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

昨天学习了装饰者模式,看老师的视频时,觉得理解了。可是刚刚看 Java设计模式.chm 文里的装饰模式时,把我给弄糊涂了。
源代码如下:
//Component
interface Person {
    void eat();
}
//ConcreteComponent
class Man implements Person {
        public void eat() {
                System.out.println("男人在吃");
        }
}
//Decorator
abstract class Decorator implements Person {
    protected Person person;  
    public void setPerson(Person person) {
        this.person = person;
    }   
    public void eat() {
        person.eat();
    }
}
//ConcreteDecorator
class ManDecoratorA extends Decorator {
    public void eat() {
        super.eat();
        reEat();
        System.out.println("ManDecoratorA类");
        }
    public void reEat() {
        System.out.println("再吃一顿饭");
    }
}
class ManDecoratorB extends Decorator {   
    public void eat() {
        super.eat();
        System.out.println("===============");
        System.out.println("ManDecoratorB类");
    }
}
//Test
public class Test {
    public static void main(String[] args) {
        Man man = new Man();
        ManDecoratorA md1 = new ManDecoratorA();
        ManDecoratorB md2 = new ManDecoratorB();     
        md1.setPerson(man);
        md2.setPerson(md1);
        md2.eat();
    }
}
编译运行结果如下:
男人在吃再吃一顿饭ManDecoratorA类===============ManDecoratorB类
问题:我不明白的是,为什么只调用md2中的eat方法,ManDecoratorA类中的内容会输出来。
我自己分析了一下,在ManDecoratorB的eat方法里调用了父类的eat方法(super.eat());而在Decorator类中调用的是person.eat();这里md1.setPerson(man);所传的参数是man,所以也就是调用了man.eat();方法,这样会输出“男人在吃”。后面的就不明白了。Man类和ManDecoratorA类似乎一点关系也没有(除了都实现了Person接口)。ManDecoratorA类跟ManDecoratorB类除了只是都继承了Decorator抽象类之外,也没有别的关系了。那么ManDecoratorA类中的eat方法究竟是如何被调用的呢?
请教大神详细解释,不胜感激!

评分

参与人数 1技术分 +1 收起 理由
菜小徐 + 1

查看全部评分

4 个回复

正序浏览

1

本帖最后由 曹冬明 于 2014-4-16 11:57 编辑

md2中的person是md1,md1中person是man,md2.eat()这里的super.eat()调用的是md1.eat(),md1.eat()这里的super.eat()调用的是man.eat(),这样条理就出来了。执行顺序就是man.eat()-->md1.eat()-->md2.eat()的最后两条语句,输出的结果就是你看到的结果,还有不懂的话就@我咯- -
回复 使用道具 举报
  1. 执行md2.eat();
  2. 也就是——
  3. super.eat();
  4. System.out.println("==============="); System.out.println("ManDecoratorB类");
  5. 看那句super.eat();它找的是Decorator类中的那个person.eat();也就是要调用成员变量的eat方法。
  6. 这是类中说的,具体到主方法的实现当中,md2的那个Person类型的成员变量是md1,所以调用md1的eat();方法。
  7. 即:
  8. super.eat();
  9.         reEat(); System.out.println("ManDecoratorA类");
  10. System.out.println("===============");
  11. System.out.println("ManDecoratorB类");
  12. 后面你就知道了,不说了。其实前边你也应该知道的,因为都是一个道理么,怎么可能后面知道前面没搞清楚。
复制代码

评分

参与人数 1技术分 +1 收起 理由
菜小徐 + 1

查看全部评分

回复 使用道具 举报
想不打印A类就直接设置md2.setPerson(man);这样就真的和A类没关系了
回复 使用道具 举报
你自己的分析我没看,我看了下代码,因为 md1.setPerson(man);md2.setPerson(md1);这两句你md2里传入的是md1,所以md2中的eat方法中的person其实是md1,所以就是调用了md1的eat方法,然后同样,md1中的eat方法中的person是man,所以会调用man的eat方法,为什么会打印A类,是因为你调用了md1的eat方法,方法中有打印A类,所以打印A类是必然的

评分

参与人数 1技术分 +1 收起 理由
菜小徐 + 1

查看全部评分

回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马