2016-01-06 3 views
0

У меня возникли трудности с пониманием того, как использовать композицию и интерфейс для поддержки композиции вместо наследования? Примером может быть:Практическое использование композиции и интерфейса в Java?

Интерфейс:

public interface IMachine { 
    void TurnOn(); 
    void TurnOff(); 
} 

машина класса является родительский класс класса принтеров

public class Machine { 

    protected boolean isOn; 

    public Machine(boolean isOn) { 
     this.isOn = isOn; 
    } 

    public void TurnOn() { 
     isOn = true; 
     System.out.println("Machine is on !"); 
    } 

    public void TurnOff() { 
     isOn = false; 
    } 

} 

Теперь, если я создаю класс принтера, который реализует IMachine интерфейса, он будет реализовывать методы интерфейса IMachine. Но, допустим, я создаю Clock Class, который реализует интерфейс IMachine, тогда я должен снова реализовать эти методы. Есть ли более эффективный способ использования композиции и интерфейса и делегирования методов классу Machine?

+0

Простое решение: просто дайте 'Machine реализует IMachine', установите' turnOn() 'и' turnOff() 'как' final' и пусть 'Printer' и' Clock extends Machine'. – Turing85

+0

@ Turing85 Точка с композицией - это * не * использовать наследование. – Andreas

ответ

2

С наследованием у вас будет базовый класс с общей логикой и подклассы, использующие эту общую логику. Любой общедоступный метод этого базового класса является общим API.

С составом интерфейс определяет общий API, каждый реализующий класс (те, которые были подклассами ранее) делегирует эти вызовы составному классу, который фактически имеет общую логику.

Наследование

public abstract class Machine { 
    public void turnOn() {/*logic here*/} 
    public void turnOff() {/*logic here*/} 
} 
public final class Heater extends Machine { 
    // heater methods here 
} 

Состав

public interface Machine { 
    public void turnOn(); 
    public void turnOff(); 
} 
final class MachineImpl { 
    void turnOn() {/*logic here*/} 
    void turnOff() {/*logic here*/} 
} 
public final class Heater implements Machine { 
    private MachineImpl impl = new MachineImpl(); 
    @Override public void turnOn() { this.impl.turnOn(); } 
    @Override public void turnOff() { this.impl.turnOff(); } 
    // heater methods here 
} 

Пользователи Machine еще будут видеть один и тот же публичный API, и пользователи Heater еще будут видеть один и тот же публичный API, но логика был перемещен.

Это позволяет Heater реализовать несколько независимых «функций», что невозможно при использовании наследования.

0

Состав, как правило, упоминается в отношениях «имеет». В этом случае композиция может использоваться, например, если у вас есть концепция объекта PowerSwitch. Это было бы выполнено в уведомлении о том, что машина имеет «PowerSwitch».

Наследование чаще всего называется отношением «является», так как в вашем принтере «есть» машинный корпус.

Использование объекта PowerSwitch, вы могли бы включать в себя функциональные возможности для использования принтера и часы, возможно, в AbstractMachine

public abstract class AbstractMachine implements IMachine { 
    private PowerSwitch machinePowerSwitch; 

    public void turnOff() { 
    machinePowerSwitch.turnOff(); 
    } 

    public void turnOn() { 
    machinePowerSwitch.turnOn(); 
    } 

    public void isOn() { 
    return machinePowerSwitch.getPowerState(); 
    } 
} 

Или что-то подобное. Принтер и часы могли бы одновременно расширять AbstractMachine.

EDIT: Перечитайте вопрос, который я вижу, вам нужна композиция ВМЕСТЕ НА НАПРАВЛЕНИИ (я читал его, поскольку вы хотели использовать оба). В этом случае просто используйте powerwitch непосредственно в классах Printer/Clock.

Смежные вопросы