2016-09-01 3 views
2

Я хочу реализовать следующий фрагмент диаграммы, используя PHP.Как реализовать композицию в php

См. composition example. Мы можем реализовать композицию на Java, используя внутренние классы.

Но в PHP нет аналога «внутреннего класса». Конечно, есть черты. Но мы можем использовать его в нескольких классах.

Я реализовал композиции, как это:

class Head { 
    private static $instance = NULL; 

    private function __construct(){} 

    public static function getInstance() { 
     $traces = debug_backtrace(); 
     if (strcmp($traces[1]['class'], 'Human')) { 
      echo "<br>Only human has head"; // Exception can be thrown here 
      return NULL; 
     } 
     if (!static::$instance) static::$instance = new self(); 
     return static::$instance; 
    } 

    public function __toString() { 
     return 'Head'; 
    } 
} 

class Human { 
    private $head; 

    public function __construct() { 
     $this->head = Head::getInstance(); 
    } 

    public function __toString() { 
     return 'I have ' . $this->head; 
    } 
} 

class Plant { 
    private $head; 

    public function __construct() { 
     $this->head = Head::getInstance(); 
    } 
} 

$human = new Human(); 
echo $human; 

$superman = new Plant(); 

Правильно ли это сделать?

Есть ли лучший способ реализовать отношения композиции в PHP?

+0

Вставьте свой код в свой вопрос в следующий раз. Кроме того, ваш код иллюстрирует простую композицию с одноэлементным классом, каков обходной путь и обходной путь для решения этой проблемы? – dbf

+0

Добавленный код. «Обходной путь», потому что, может быть, есть лучший способ сделать это :) Более родной для PHP, как внутренние классы на Java. – profport

+0

где вы читали эту композицию о внутренних классах? – Wes

ответ

10

Похоже, вы действительно смущен о том, что «композиция» находится в ООП.

Состав - это ассоциация между двумя классами, где для экземпляра первого класса, подлежащего инстанцированию, обязательно предоставляется его вторым классом. В вашей конкретной диаграмме для Human существует, требуется Head. В коде это будет:

class Head { 
} 

class Human { 
    private $head; 
    public function __construct(Head $head) { 
     $this->head = $head; 
    } 
} 

$bob = new Human(new Head); 

И все. Нет debug_backtrace() и не одиночный анти-шаблон. И, кстати, это выглядело бы почти точно так же и на Java, даже с возможностью иметь внутренние классы.

Что касается вашего опубликованного кода. Это было бы неправильно:

if (strcmp($traces[1]['class'], 'Human')) { 
    echo "<br>Only human has head"; // Exception can be thrown here 
    return NULL; 
} 

Диаграмма не говорила, что только люди имеют голову. Только тот человек должен иметь головку, подлежащую созданию. У вас также может быть $skipper = new Dog(new Head);, что было бы прекрасно.

+0

Спасибо @ tereško, я был очень смущен. Я думал, что композиция означает: ** только ** Человек имеет голову. Возможно, ваш код ближе к агрегации. По составу, как я знаю, мы должны создать экземпляр некоторого класса ** внутри ** другого класса. Например. общественная функция __construct() { $ this-> head = new Head(); } – profport

+0

Конечно, в большинстве ситуаций может быть полезно повторно использовать класс Head в других классах. Но возможно ли ограничить состав в диаграмме UML? То есть ** только ** Человек имеет голову? Иногда это может быть необходимо. – profport

+1

Нет, это невозможно ограничить, но у вас есть требование, чтобы у человека '' HumanHead', который расширяет 'Head'. Я также предостерег бы от попыток увязать ООП в каком-то контексте «реального мира». Программирование не касается реального мира, а абстракций. –

2

Состав над наследованием.

В основном Состав - это более прочная форма агрегация. Можно сказать, что отношения между телом и головой - это композиция, потому что мы не можем жить без головы, но отношения между телом и рукой - это агрегация, потому что мы можем потерять руку, но мы можем остаться в живых. Есть также более слабые отношения, такие как прямые ассоциации и временная ассоциация.

Инъекционная инъекция, однако, представляет собой лишь образец, в котором мы создаем эти ассоциации (путем ввода одного класса в другой).

В большинстве случаев вы могли распознать композиционное отношение конструктором, который вводит другой объект и присваивает его его свойству и жизненному циклу конца объекта и начинается в тот же момент.

Помимо этого, с технической точки зрения, нет никакой разницы между реализацией каждой ассоциации. Это скорее определение отношения, а не реализация.

Отношение композиции часто используется для перезаписывания/изменения или улучшения поведения класса введенных объектов.Не слишком волнуйтесь и не волнуйтесь о композиции. В большинстве случаев преимущества по сравнению с наследованием малы и больше всего нравятся сторонним разработчикам библиотек, которые используют композицию для дополнительной гибкости своих библиотек.

Наследование от родительского класса и методов перегрузки/добавления дает нам аналогичную функциональность, но с составом мы получаем большую гибкость. Например, если наш конструктор принимает объект, который наследует интерфейс Head, мы можем использовать класс HumanHead, если он расширяет интерфейс Head, но мы могли бы также использовать наш класс для улучшения других существ, которые простираются от того же интерфейса, что и DogHead или DuckHead ...

Это возможно, не лучший пример, но он показывает основную концепцию.

Обязательно проверьте этот [Aggregation vs Composition vs Association vs Direct Association] и этот [Association-Aggregation-Composition-Dependency].

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