我遇到过一种情况,我想避免使用$GLOBAL
状态,但无法弄清楚如何做到这一点。我相信反射和依赖注入可以解决这个问题:
这是一个人为的例子(是的,我知道它有点弯曲......假设我们有一个Calculator
类和辅助函数,基本上复制了它的功能,例如add, subtract
.现在,我们还希望可以访问计算history
。
如何使用这些帮助程序函数,而不必手动插入Calculator
作为依赖项?
class Calculator
{
private $history = [];
public function add(int $a, int $b): int
{
$result = $a + $b;
$this->history[] = $result;
return $result;
}
public function subtract(int $a, int $b): int
{
$result = $a - $b;
$this->history[] = $result;
return $result;
}
public function history(): array
{
return $this->history;
}
}
function add(int $a, int $b): int
{
$calculator = new Calculator;
return $calculator->add($a, $b);
}
function subtract(int $a, int $b): int
{
$calculator = new Calculator;
return $calculator->subtract($a, $b);
}
function history(): array
{
$calculator = new Calculator;
return $calculator->history(); // Clearly this will be empty
}
明白我的意思吗?当前调用history()
当然会返回一个空数组...
当然,这将起作用:
function add(Calculator $calculator, int $a, int $b): int
{
return $calculator->add($a, $b);
}
function history(Calculator $calculator): array
{
return $calculator->history();
}
尽管如果我将其用作软件包,则很容易出错,手动连接这些依赖项会耗费大量人力......更不用说每次调用帮助程序函数了。
另一种有效的方法是全局变量:
$GLOBALS['calculator'] = new Calculator;
function add(int $a, int $b): int
{
return $GLOBALS['calculator']->add($a, $b);
}
function history(): array
{
return $GLOBALS['calculator']->history();
}
虽然。。。玉玉玉。不,谢谢。
帮助!
这通常是当人们转向 IoC(又名 DI 容器(时。
您还可以使用单一实例模式,为类的单个实例提供静态访问器。 您可以在计算器类中跟踪历史记录或状态,因为此类只有一个实例。
class Calculator
{
private static $instance;
public static getInstance(): Calculator
{
if (static::$instance === null) {
static::$instance = new Calculator;
}
return static::$instance;
}
...rest of code...
}
Calculator::getInstance()->add($x, $y);
静态的主要关注点是状态和可测试性,你对全局函数使用$GLOBALS对我来说似乎没有太大问题,因为你本质上是使用$GLOBALS作为容器或服务定位器。