PHP OOP访问方法的良好实践?
我有一些代码通常是这样的:PHP OOP访问方法的良好实践?,php,oop,methods,Php,Oop,Methods,我有一些代码通常是这样的: private $user; public function __construct() { $this->user = User::getInstance(); //singleton } public function methodOne() { return $this->user->foo(); } public function methodTwo() { return $this->user->f
private $user;
public function __construct()
{
$this->user = User::getInstance(); //singleton
}
public function methodOne()
{
return $this->user->foo();
}
public function methodTwo()
{
return $this->user->foo2();
}
public function methodThree()
{
return $this->user->foo3();
}
$user = new UserWrapper(User::getInstance());
我想,如果我将user属性设置为实例,我可以在方法中重用一个较短的名称(在本例中,它并没有那么短)。我还认为这样做可能会节省一些资源(开始怀疑),但当我看别人的代码时,我很少看到有人这样做。他们通常只会打电话:
User::getInstance()->foo();
User::getInstance()->foo2();
User::getInstance()->foo3();
这方面有什么最佳实践吗?如果这不是一门独生子女课程,你可能会这样做?或者你不应该这样做?希望得到一些澄清,谢谢
编辑:
如果有任何误解,我只是想知道我是否应该在第一个示例中创建一个属性来存储实例,而不是:
public function methodOne()
{
return User::getInstance()->foo();
}
public function methodTwo()
{
return User::getInstance()->foo2();
}
public function methodThree()
{
return User::getInstance()->foo3();
}
实际上,现在我想这可能是更少的代码,因为我不需要构造函数…我个人在PHP中的偏好是只使用静态方法的类来处理单例,所以
User::foo();
User::bar();
我不会创建一个新类,只是为了围绕这样一个单例。但是如果您的新类添加了一些额外的逻辑,那么您的示例就有意义了。请记住,如果您担心过于冗长,您可以始终使用临时变量进行后续函数调用
$user = User::getInstance();
$user->foo();
$user->bar();
但就我个人而言,我不再使用单身。相反,我使用依赖注入。我喜欢sfServiceContainer,但还有其他的。请看本系列文章:
更新
根据其他评论,我将这样做:
class UserWrapper
{
private $user = null;
public function __construct($user)
{
$this->user = $user;
}
public function foo()
{
return $this->user->foo();
}
...
}
然后像这样使用它:
private $user;
public function __construct()
{
$this->user = User::getInstance(); //singleton
}
public function methodOne()
{
return $this->user->foo();
}
public function methodTwo()
{
return $this->user->foo2();
}
public function methodThree()
{
return $this->user->foo3();
}
$user = new UserWrapper(User::getInstance());
为什么??因此,如果我想测试UserWrapper类,我可以传入一个假用户对象。例如:
class UserMock { ... } // A fake object that looks like a User
$userTest = new UserWrapper(new UserMock());
我通常这样做,如果您已经在某种引导或配置文件中包含了该类。我通常会在引导文件中声明$user变量,该变量在每次页面加载时都会被调用,然后在其他php文件中将其作为全局变量引用,这就是我在引导文件中的内容
$user = new User();
那么这就是我在调用php文件中的内容
global $user;
$user->foo();
你的方法确实存在一些问题
- 不清楚您的类是否依赖于用户类。您可以通过将用户添加为构造函数参数来解决此问题李>
- 单身往往是不好的习惯。您的代码演示了原因:它是全局可访问的,因此很难使用它跟踪依赖项(这就指向了上述问题)
- 静态方法经常被用作全局访问点(响应您看到的人们通常所做的操作User::method())。全局接入点与单例接入点存在同样的问题。它们也更难测试
class Foo {
public function __construct(User $user) {
$this->user = $user;
}
public function doXsimplified() {
$this->user->doXbutMoreComplex($arg1,$arg2, $arg20);
}
}
可以通过
\uuu callStatic
最简单地实现,我相信在phpYea中使用globals不是“良好的oop实践”之一,也会有一些额外的逻辑。这是一种与另一个应用程序的集成,因此我包装用户类方法,然后决定更改应用程序,而不必重命名所有内容。对于您展示的代码,我是这样做的,但我只是想知道,如果在每个方法中只使用一次实例,那么最好的方法是什么。编辑了我的主要帖子。如果你添加了额外的逻辑,那么你的代码就可以了。我唯一要改变的是,不要在构造函数中获取User
的实例,而是将其作为参数传递给构造函数(以方便依赖项注入)。抱歉,也许我还没有很好地解释自己,我只是想知道存储变量的实例是否比直接调用实例更好,如上面两个示例所示。我倾向于第二种方式(每次直接呼叫),因为它看起来更清晰。我会使用第一种方式。我已经用一个例子更新了我的答案。编辑了我的帖子,我还创建了包装器,因为它正在与另一个应用程序集成,所以如果我以后更改应用程序,我不必重命名我的所有方法。我也不确定我是否能够使用您显示的方法,因为我还没有用户对象?@Joker包装器的用途很好。您的用户对象在包装器对象出现的那一刻起作用(因为它是用来操纵第三方用户对象的)。因此,如果你在创建另一个用户对象之前或之后创建这个用户对象,不会有什么区别。是的,没有区别,我想我仍然没有很好地描述自己。实际上要简单得多。我想知道是应该将实例存储在构造函数设置的属性中,还是直接获取实例(如上面的两个示例所示)。我想这只是一种偏好?我现在倾向于第二种方式,因为它似乎让事情变得更清楚。@Joker我会遵循“孤立变化”的规则。什么地方最有可能发生变化?如果发生变化,什么将为您节省最多的工作(无论差异有多小)?然而,如果你发现第二个例子更清楚,那就是一个支持这个观点的论点。