2017-02-03 15 views
1

На теме «предпочитают композиции над наследованием», мой учитель говорит, что это:Состав, экспедиционные и Обертывание

  • состав: существующий класс становится компонентом новой один
  • пересылки: каждый метод экземпляра в новом классе, вызывает соответствующий метод на содержащемся экземпляре существующего класса и возвращают результаты
  • обертку: новый класс инкапсулирует существующий

Я не очень хорошо понимаю эти три понятия, так что я пытаюсь записать код:

//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 
    } 
} 

И так, что упаковка?

ответ

1

Ваш первый пример - это не композиция.

Composition является «has-a» отношения между 2 объектами, где один объект (состоит объект) является членом поле другого (владелец).

Состав будет:

class DemoA { 
    DemoB b; //composition 
} 

Мы бы сказали, "DemoA состоит из дембеля".

Если 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), поэтому мы обернуть его в тип, который обрабатывает поведение для нас, так что мы Арен» постоянно переписывая такое поведение.

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 
    } 
} 

Здесь вы называете точно таким же метод в составленном, например, как в случае, композитор: метод doSomething().
Вы можете добавить, конечно, некоторые другие методы в классе B.