我认为由于糟糕的设计决定,我可能会碰壁。
我正在开发一个类层次结构,它有一个抽象基础,几个类可以从中扩展。在没有深入了解原因的“细节”的情况下,这些类的实例函数需要“上下文”对象可用 - 当前操作对象。
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
对象(,反之亦然,以及任何其他继承类)可能导致需要在给定时间传递大量上下文对象 - 我不知道认为这是一个解决方案。
答案 0 :(得分:1)
我将继续发布这个作为答案,因为我相信这是你最终努力的目标。
我相信你发现的问题是你有抽象类属性$_context
,它被设置为存储单个上下文,但为了使其正常工作,你真的需要在/中的引用由实际的班级本身。因此,在您的示例中,$_context
属性实际上是对当前对象上下文的引用,而不是扩展AbstractBase
的所有实例化类的单个上下文。
这当然没有意义。我建议的是调整当前的静态$_context
并将其用作存储来保存和检索引用,在设置上下文时返回唯一ID并将该ID放入$this->context_id
所以对象可以通过引用继续获取它的上下文:
<?php
abstract class AbstractBase {
protected static $_context;
private $context_id;
public static function setContext($context) {
$context_id = uniqid(php_uname('n'), true);
self::$_context[$context_id] = $context;
return $context_id;
}
public function getContext() {
return self::$_context[$this->context_id];
}
public function myPrint() {
print_r($this);
print_r(self::$_context);
}
}
class test1 extends AbstractBase {
public function __construct($context){
$this->context_id = self::setContext($context);
}
}
class test2 extends AbstractBase {
public function __construct($context){
$this->context_id = self::setContext($context);
}
}
$test1 = new test1('this stuff');
$test2 = new test2('other stuff');
$test1->myPrint();
$test2->myPrint();
?>
答案 1 :(得分:0)
看起来有点强迫。我认为具有静态方法的“常规”基类 - 或者具有静态对象将是更好的策略。