Можно ли использовать здесь какой-нибудь паттерн?

seine

Новичок
Привет всем. У меня есть три объекта, классы которых унаследованы от общего абстрактного объекта. И с этими объектами я делаю одни и те же действия.

PHP:
abstract class Area
{
    public function isCoveredBy($human) {/* реализация метода */};

    public abstract function add($human);
}

class RedArea extends Area {}
class BlueArea extends Area {}
class WhiteArea extends Area {}

// Теперь другой кусок кода, где эти areas используются
// На самом деле, этот массив получается где-то раньше в коде
// (может быть даже в другом методе!), но чтоб не вводить в 
// заблуждение, пишу здесь
$areas = array(
    new RedArea(),
    new BlueArea(),
    new WhiteArea(),
);

foreach ($areas as $area) {
    if ($area->isCoveredBy($human)) {
        $area->add($human);
        break;
    }
}
Надеюсь понятно. Возникла мысль, что вместо перебора объектов в цикле, можно было использовать какой-нибудь шаблон. Другая мысль мне даже упорна стала доказывать, что я где-то читал про этот чудо-шаблон. А третья - что надо пренепременейшим образом использовать именно его =)
Я оставлю в таком виде как сейчас (через цикл), следуя здравому сымслу (не плоди сущности без надобности и все такое), но хочется узнать, есть ли на самом деле какой-то шаблон, который бы использовался в похожих случаях? Пробежался по нескольким основным и такого не нашел =( Не мог же он мне присниться... хотя и такое бывало.
Сорри, за создание такой немного бессмысленного темы.
 

craz

Нестандартное звание
зачем там брейк?
человека только в одну арию можно добавить?
 

Adelf

Administrator
Команда форума
seine
Эти три обьекта работают как одно целое. Имхо, нужен класс-контейнер, который этими тремя объектами будет заниматься.
И все функции типа addHuman там реализовывать.
 

seine

Новичок
Ага, кажется понял.
PHP:
class Container
{
    private $_areas = array();

    public function addArea(Area $area) 
    {
        $this->_areas[] = $area;
    }

    public abstract function cookHuman();
    
    // Метод сам разруливает в какую зону 
    // добавлять человека
    public function addHuman()
    {
        foreach ($this->_areas as $area) {
            if ($area->isCoveredBy($human)) {
                $area->add($human);
                break;
            }
        }
    }
}
Что-то вроде этого?
 

Adelf

Administrator
Команда форума
PHP:
addHuman($human)
Примерно так, да. Но я не знаю как у тебя еще они используются.
 

seine

Новичок
Ок, спасибо =)
PHP:
addHuman($human)
Точно, $human забыл.
У меня пока только так и используются. Т.е. сначала идет проверка, и если условие верное, то добавить человека в зону.
 

whirlwind

TDD infected, paranoid
Зачем вводить новый интерфейс Container? Если решение так и так принимает area, то бессмыслено выносить isCoveredBy в интерфейс area - это переливание ответственности на внешний код, там где оно не нужно. Оставьте IArea::addHuman($human), который return boolean и будет Container implements IArea. Будете вместо гдето там инициализации массива делать инициализацию контейнера:

PHP:
// гдето там
$areas = new CompositeArea();
$areas->addArea(new RedArea());
$areas->addArea(new BlueArea());
$areas->addArea(new WhiteArea());

// гдето между
$areaUser = new MyController($areas);
$areaUser->execute();

// гдето тут
class MyController {
    private $area;
    function __construct(IArea $anyAreaImplementation) {
         $this->area = $anyAreaImplementation;
    }

    function execute() {
        // ....
       $this->area->addHuman($human);
    }

}
 

Adelf

Administrator
Команда форума
whirlwind
Коллекции итемов прикидываться итемом... опасно имхо. Телепат? :)
Я вот не знаю какая у него ситуация. Мне вообще показалось. что Human в данном случае должен уметь добавлять себя в Areas, но решил промолчать.
 

craz

Нестандартное звание
whirlwind
Коллекции итемов прикидываться итемом... опасно имхо. Телепат? :)
Я вот не знаю какая у него ситуация. Мне вообще показалось. что Human в данном случае должен уметь добавлять себя в Areas, но решил промолчать.
ага мне кажется это перемещалка персов в какой то браузерке.. только я не придумал на нее патерна)
 

seine

Новичок
Зачем вводить новый интерфейс Container? Если решение так и так принимает area, то бессмыслено выносить isCoveredBy в интерфейс area - это переливание ответственности на внешний код, там где оно не нужно. Оставьте IArea::addHuman($human), который return boolean и будет Container implements IArea. Будете вместо гдето там инициализации массива делать инициализацию контейнера:

PHP:
// гдето там
$areas = new CompositeArea();
$areas->addArea(new RedArea());
$areas->addArea(new BlueArea());
$areas->addArea(new WhiteArea());

// гдето между
$areaUser = new MyController($areas);
$areaUser->execute();

// гдето тут
class MyController {
    private $area;
    function __construct(IArea $anyAreaImplementation) {
         $this->area = $anyAreaImplementation;
    }

    function execute() {
        // ....
       $this->area->addHuman($human);
    }

}
Ого, сразу столько вопросов.
А в каком месте кода определяеть, в какую зону добавить человека?

решение так и так принимает area, то бессмыслено выносить isCoveredBy в интерфейс area - это переливание ответственности на внешний код
Внешний для area? Т.е. определять, куда добавить пользователя должен класс с пользователем? И метода isCoveredBy больше не будет?

Оставьте IArea::addHuman($human), который return boolean
В зависимости от чего возвращать true или false? Удачно ли добавлен пользователь (true/false) или можно ли его добавлять?

и будет Container implements IArea
CompositeArea и есть этот самый Container?
 

whirlwind

TDD infected, paranoid
> А в каком месте кода определяеть, в какую зону добавить человека?

> Внешний для area? Т.е. определять, куда добавить пользователя должен класс с пользователем? И метода isCoveredBy больше не будет?

> В зависимости от чего возвращать true или false? Удачно ли добавлен пользователь (true/false) или можно ли его добавлять?

> CompositeArea и есть этот самый Container?

Это связанные вопросы. Я говорю по факту того, что ты предоставил в первом посте. Алгоритм и результат не меняется, меняются только отношения между классами.

PHP:
class CompositeArea {
    ...
    function addHuman($human) {
        foreach ($this->_areas as $area) {
            if ($area->addHuman($human)) return true;
        }
    }
    ...
}
Теперь они (различные areas и пользовательский код, которого у тебя по сути нет в примере) не связаны там, где в этом нет нужды. То есть связанность кода понизилась - это хорошо с точки зрения архитектуры. Это все что я могу сказать по твоему коду. Если это не то или не подходит, то тут надо объяснить суть задачи.
 

HraKK

Мудак
Команда форума
На будущее если встречается что-то типа
PHP:
$areas = array(
    new RedArea(),
    new BlueArea(),
    new WhiteArea(),
);

foreach ($areas as $area) {
    if ($area->isCoveredBy($human)) {
        $area->add($human);
        break;
    }
}
То это паттерн Visitor
 

whirlwind

TDD infected, paranoid
HraKK тогда надо добавить, что это относится к выделению isCoveredBy($human) в отдельный интерфейс.
 

HraKK

Мудак
Команда форума
whirlwind
Естественно. Почитав о паттерне, это станет ему понятно. Надеюсь.
 
Сверху