Полиморфный / Классы Plugable PHP

У меня есть вопрос, который является sonewhat больше вопроса о дизайне. У меня есть класс, который определяет набор функций. Однако я хочу это, поведение некоторых функций является изменяемым во время времени выполнения - или по крайней мере рабочим как сменный интерфейс в течение времени проектирования. например:

class MyClass {  
  public function doSomething();
}

$obj = new MyClass();
// PSEUDO CODE
$obj->doSomething = doSomethingElse;
$obj->doSomething(); // does something else

У меня были различные Идеи, как реализовать что-то вроде этого в "реальном" коде. Однако я не совсем уверен, который является правильным способом пойти. Я сначала думал, что мог использовать Интерфейс с этой целью.

interface IDoSomethingInterface {  
  public function doSomething();
}

class DoSomethingClass implements IDoSomethingInterface
{
  public function doSomething()
  {
    // I do something!
  }
}

class DoSomethingElseClass implements IDoSomethingInterface
{
  public function doSomething()
  {
    // I actually do something else!
  }
}

class MyClass {
  public doSomething(IDoSomething $doSomethingProvider)
  {
    $doSomethingProvider->doSomething();
  }
}

$obj = new MyClass();
$doSomethingProvider = new DoSomethingClass();
$doSomethingElseProvider = new DoSomethingElseClass();

$obj->doSomething($doSomethingProvider); // I do something!
$obj->doSomething($doSomethingElseProvider); // I do something else!

Этот подход мог быть расширен, чтобы не передать doSomething поставщика в качестве параметра, но установить его или как элемент объекта или даже как участника класса. Однако мне не нравилось это, я должен создать экземпляр n класса, который даже не содержит единственную членскую переменную, и единственный метод мог легко быть статической функцией класса. Нет только никакой потребности в объекте в той точке imo. Я затем собирался попытаться использовать функциональные переменные - но я упаду из ООП затем, которое я не любил также. Мои вопросы: который является лучшим способом реализовать систему как, я описал? Какой подход Вы попробовали бы или использовали бы? Действительно ли там что-нибудь очевидно, что я, возможно, не думал? Или я должен просто пойти с интерфейсным подходом, и мое плохое чувство о instanciating 'bodyless' объекты является просто ценностью компьютерного фаната?! Мне любопытно на предмет Ваших ответов!

Править:

Поскольку я действительно интересуюсь разъяснением, если это на самом деле будет (или должен быть), состояние или Стратегическая модель, то я буду вдаваться еще в некоторые подробности о реализации. У меня есть базовый класс наборов, из которых я получаю различные определенные реализации. Я хочу смочь выбрать единственный элемент из любой определенной реализации - однако, я хочу смочь, динамично изменяются, как этот элемент выбран из набора, например:

class MyCollection implements Countable, ArrayAcces, Iterator
{
  // Collection Implementation   
  public function select(ISelectionStrategy $strategy)
  {
    return $strategy->select($this);
  }   
} 

interface ISelectionStrategy
{
  public function select(MyCollection $collection);
}  

class AlphaSelectionStrategy implements ISelectionStrategy
{
  public function select(MyCollection $collection);
  {
    reset($collection);
    if (current($collection))
      return current($collection);
    else
      return null;
  }
}

class OmegaSelectionStrategy implements ISelectionStrategy
{
  public function select(MyCollection $collection)
  {
    end($collection);
    if (current($collection))
      return current($collection)
    else
      return null;
  }
}

class RandomSelectionStrategy implements ISelectionStrategy
{
  public function select(MyCollection $collection)
  {
    if (!count($collection))
      return null;
    $rand = rand(0, count($collection)-1);
    reset($collection);
    while($rand-- > 0)
    {
      next($collection);
    }
    return current($collection);
  }
}

$collection = new MyCollection();
$randomStrategy = new RandomSelectionStrategy();
$alphaStrategy = new AlphaSelectionStrategy();
$omegaStrategy = new OmegaSelectionStrategy();

$collection->select($alphaStrategy); // return first element, or null if none
$collection->select($omegaStrategy); // return last element, or null if none
$collection->select($randomStrategy); // return random element, or null if none 

Это - basicly, чего я хочу достигнуть. Это теперь больше реализация стратегической модели или шаблон состояния - хотя я использовал термин стратегия, потому что это соответствует больше в этом случае так или иначе. Насколько я понимаю стратегию и заявляю шаблону basicly, то же, кроме их намерения отличается. Ссылка, предоставленная Gordon, указывает, что намерение шаблона состояния, "Позволяют объекту изменить его поведение, когда его внутреннее состояние изменяется" - но это это не случай здесь. То, что я хочу, должно смочь сказать, что мой класс MyCollection "использует это или тот алгоритм, чтобы дать мне, элемент" - не "дает мне элемент с помощью алгоритма, который Вы определяете через свое собственное состояние". Надежда кто-то может разъяснить это!

С наилучшими пожеланиями, Daniel

7
задан Daniel Baulig 31 January 2010 в 14:24
поделиться

2 ответа

Ваш подход верен. Это Strategy Pattern (UML диаграмма):

Проверьте мой ответ на этот вопрос (перейдите к тому, где написано Так как вы хотите динамически изменять поведение):

Альтернативой вашему конкретному UseCase было бы капсулирование стратегий выбора в один класс Service, вместо того, чтобы присваивать их вашему классу Collection. Затем вместо передачи стратегий в коллекцию, передайте коллекцию в класс Service, например,

class CollectionService implements ICollectionSelectionService
{
    public static function select(MyCollection $collection, $strategy) {
        if(class_exists($strategy)) {
            $strategy = new $strategy;
            return $strategy->select($collection);
        } else { 
            throw new InvalidArgumentException("Strategy does not exist");
        }    
    }
}
$element = CollectionService::select($myCollection, 'Alpha');

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

Для других поведенческих моделей проверьте

4
ответ дан 7 December 2019 в 07:45
поделиться

Решение, которое вы изложили, более или менее правильно. Вы можете не знать это, но это на самом деле Узор дизайна «Государства» . Состояние системы представлено объектом. Если вам нужно изменить состояние, вы просто замените объект другим состоянием.

alt text

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

3
ответ дан 7 December 2019 в 07:45
поделиться
Другие вопросы по тегам:

Похожие вопросы: