Я думаю, что, возможно, попал в стену из-за плохих дизайнерских решений.
Я работаю над иерархией классов, с абстрактной базой, из которой выходят несколько классов. Не вдаваясь в подробности того, почему функции экземпляров этих классов требуют наличия объекта «контекст» - текущего работающего объекта.
abstract class AbstractBase{
protected static $_context;
protected $_parent;
public static function get_context(){
return static::$_context;
}
protected static function set_context(self $context, &$previous = null){
$previous = static::get_context();
static::$_context = $context;
}
public function __construct(){
$this->_parent = static::get_context();
}
public function do_something($callback){
static::set_context($this, $previous);
$callback();
static::set_context($previous);
}
}
class ConcreteOne extends AbstractBase{
}
class ConcreteTwo extends AbstractBase{
}
Это прекрасно работает, за исключением того, что ConcreteOne
и ConcreteTwo
необходимо отслеживать их собственный контекст - текущее определение приведет к тому, что любое изменение контекста любого наследуемого класса перезапишет AbstractBase::$_context
. Это изменение достаточно легко осуществить:
class ConcreteOne extends AbstractBase{
protected static $_context;
}
class ConcreteTwo extends AbstractBase{
protected static $_context;
}
Теперь конкретные реализации будут управлять своими собственными контекстами. Это, однако, представляет собой небольшую проблему; любые клиентские классы, расширяющие базовый класс, будут иметь статический член с именем $_context
.
Это воняет мне плохим дизайном, но опять же, мой нос еще не самый острый. Я задаюсь вопросом, не выбрал ли я здесь плохой путь, и самое главное, должен ли я продолжить этот путь или прервать его и изменить его.
Итак, я должен идти вперед или кто-то может предложить лучшее решение для управления "статическим" контекстом между экземплярами?
Примечание : я рассмотрел передачу объекта $context
в качестве аргумента $callback
, однако, поскольку ConcreteOne
обратные вызовы могут создавать экземпляры объектов ConcreteTwo
и вызывать их ( и наоборот, и любой другой наследуемый класс ), который может привести к тому, что большое количество объектов контекста необходимо будет передать в определенный момент времени - я не думаю, что это решение.