组成,转发和包装

时间:2017-02-03 17:40:00

标签: java composition

关于"更喜欢构图而非继承",我的老师说:

  • 组成:现有的类成为新类的组件
  • 转发:新类中的每个实例方法,在现有类的包含实例上调用相应的方法并返回结果
  • 包装器:新类封装了现有的

我不太了解这三个概念,所以我试着写下一些代码:

//Composition is this
Class A{
    public void doSomething(){
        //do some code
    }
}

Class B{
    A a = new A();
    public void doOther(){
        a.doSomething();  //this is forwarding
    }
}

什么是包装?

2 个答案:

答案 0 :(得分:2)

你的第一个例子不是作文。

Composition是两个对象之间的“has-a”关系,其中一个对象(组合对象)是另一个对象的字段成员(所有者)。

组成将是:

class DemoA {
    DemoB b; //composition
}

我们会说“DemoA由DemoB组成”。

如果在DemoB无法访问时DemoA对象仍然可用,我们会将DemoB视为aggregated。例如,尽管密钥环可能已被破坏,仍然可以使用密钥。密钥环将由密钥组成,但不拥有它们,表示聚合。

您的转发示例看起来很好,虽然要求确实说“返回结果”,这可能表明方法不应该是无效的:

class DemoA {
    private DemoB b;

    public int doSomething() {
        return b.doSomething(); //forwarding/delegating
    }
}

对于包装器,它们封装了对象的行为,暴露了新的(通常更复杂的)行为。一个示例是DataInputStream,当InputStream只能处理原始数据时,它会包含String以允许您读取InputStream个对象等等。

class DemoB {
    public int read() {
        //...Read one int of data
    }
}

class DemoA {
    private DemoB b;

    public DemoA(DemoB b) {
        this.b = b;
    }

    public List<Integer> readUntil(List<Integer> dataList, Supplier<Boolean> condition) {
        while(condition.get())
            dataList.add(b.read());

        return dataList;
    }
}

在此示例中,DemoA包装DemoB以展示readUntil行为,DemoB无法执行此操作。

这有点愚蠢的例子,但希望表达了这一点:我们的DemoB对象无法执行我们需要的行为( readUntil ),所以我们将它包装在一个处理我们的行为,所以我们不会经常改写这种行为。

答案 1 :(得分:0)

  

现有的类成为新类的一个组件

Versus

  

新类封装了现有的

听起来多余。

包装和构图确实在概念上传达了同样的东西。

在您的实际示例代码中:

class A{
    public void doSomething(){
        //do some code
    }
}

class B{
    A a = new A();
    public void doOther(){
        a.doSomething();  //this is forwarding
    }
}

B类组成A实例,因为它将A实例存储在其状态中,并在doOtherMethod()实现中使用它。
但是,您执行包装/合成但不使用调度模式,因为调用的方法在编写器和组合实例之间不对称。您确实致电b.doOther(),呼叫a.doSomething()

基本的调度模式如下:

class A{
    public void doSomething(){
        //do some code
    }
}

class B{
    A a = new A();
    public void doSomething(){
        a.doSomething();  //this is forwarding
    }
}

在此,您在组合实例中调用与在composer实例中完全相同的方法:doSomething()方法。
你当然可以在B类中添加一些其他方法。