【问题标题】:PHP singletons and use of extended static propertiesPHP 单例和扩展静态属性的使用
【发布时间】:2012-12-20 09:21:10
【问题描述】:

我已经为这个问题转了几个小时。 也许这根本不可能,或者对此有更好的 OOP 解决方案......

例如:我有两个班级

class Base
{
    public static $config;
}

class System extends Base
{
    public function __construct()
    {
        self::$config = 2;
    }
}

class Core extends Base
{
    public function __construct()
    {
        self::$config = 3;
    }
}

我总是以单例的形式访问这些类:System::HelloWorld(), Core::DoStuff();

我希望 $Config 属性从 Base 类继承,因为我需要它 几乎每一个类,为什么要一遍又一遍地定义它。

问题是,$Config 属性将自己覆盖为 sonn,因为另一个类为其设置了自己的值:

System::$config = 2;
Core::$config = 3;
print System::$config // it's 3 instead of 2

我确实理解为什么会发生这种情况:因为 Base::$Config 是静态的 - 并且以这种方式 - 由所有孩子共享。我不想要这个,我希望它在每个孩子中都是静态的,但不是它的孩子的低谷。如果我真的实例化 System 和 Core 类,那没问题,但我需要它们作为 Singletons...

帮帮我,也许你知道比这个更好的设计模式。

【问题讨论】:

  • 你知道单例和静态很难用单元测试覆盖。使用这种方法通常被认为是不好的做法。如果您有兴趣改进您的整体方法,我并不是说一定是这样,而是思考和阅读。
  • 我也不是他们的粉丝。但我想提供对所有不同模块的简单访问,而不需要实例化它们,跟踪实例,将相同的实例注入到所有需要它的类中等等。很长的路要走:$a = new a() ; $a->Foo();回声 $a->x;所需方式:a::Foo();回声 a::$x;
  • 如果这件事很严重,我保证会再次困扰你。但是,请按照自己的方式自己找出答案,可能每个人都必须这样做:)。
  • 如果您使用:a::$x,$x 必须是静态属性,因为该类用作静态属性。现在想象一下,b 类也有一个属性 $x,但有另一个值 (b::$x)。那么为什么要在每个类中一遍又一遍地将 $x 定义为静态属性,如果您可以构建一个具有 $x 属性的父类,并且所有其他类都继承自它。但是现在:类被用作静态,所以父级也必须是静态的,如果它是静态的,那么所有将其作为父级的类都将共享 $x。
  • @markus 四年后,我在这里为我的设计决策大笑。那时我应该阅读一些有关软件设计的基础书籍。 2017 年的 Me 完全同意 2013 年的 you (marcus) :)

标签: php class properties static singleton


【解决方案1】:

你根本不需要使用静态变量,

<?php
Class Base{
 public $Config;
}

Class System Extends Base{
 Public static $obj = null;
 Public static Function HelloWorld() {
  if (!System::$obj) System::$obj = new System();

  // call the object functions
  // $obj->HelloWorld();
 }

 Public Function __Construct()
 {
     $this->Config = 2;
 } 
}

Class Core Extends Base{
 Public Function __Construct()
 {
     $this->Config = 3;
 }
}
?>

【讨论】:

  • 但我永远不会实例化 System 和 Core 类...如果我调用 System::$parent::$Config = 999;然后打印 System::$parent::$Config - 它不会是 999,因为它不是静态的并且该值丢失了?
  • 单例模式是一种将类的实例化限制为一个对象的设计模式。所以你应该在你的静态函数中实例化一个对象,比如 System::HelloWorld()。
  • 我明白了。如果你直接使用你的类,你怎么称呼它,没有实例化。不是:$instance = new System(); $instance->HelloWorld();但是:System::HelloWorld()
  • 我在答案中更新了 System 类。该类有一个静态变量 $obj ,它保存着唯一的对象。静态函数 HelloWorld 仅在必要时才实例化单例。
  • 在我看来,这并不是一个真正干净的解决方案,一直获取实例等等。这意味着,每个方法都必须一遍又一遍地实例化类......我必须使用另一种方法,或创建完全静态的类。
【解决方案2】:

我为此想出了一个相对较好的解决方案。可能遇到同样问题的朋友,请看here

【讨论】:

  • 请不要使用这个解决方案:)
【解决方案3】:
<?php
// static change the attributes of the scope
class base
{
    public static $config;

}

class a extends base
{
    public function __construct()
    {
        self::$config = 1;
    }
}
class b extends base
{
    public function __construct()
    {
        self::$config = 2;
    }
}

a::$config = 2;
b::$config = 3;
echo a::config, ',', b::$config; // 3,3
$a = new a();
echo base::$config, a::$config, b::$config, $a::$config; // 1 1 1 1

【讨论】:

  • 这很好地解释了我的问题 =) 你有解决方案吗?
  • 这如何解决问题?
猜你喜欢
  • 2013-10-10
  • 2014-10-05
  • 2016-08-10
  • 2011-05-27
  • 1970-01-01
  • 2011-06-11
  • 1970-01-01
  • 1970-01-01
  • 2010-11-19
相关资源
最近更新 更多