我有一个类有一些相当大的方法。在它的基本和最常见的状态中,大多数功能都不是必需的,所以我想知道是否有一种延迟加载只是部分类的方法。这些方法需要能够访问私有/受保护的成员,因此如果方法是本机的,那么它将是理想的,但是在寻找我遇到的其他解决方案时this讨论了在回调中使用私有成员的问题。一个可行的解决方案(我使用单独的类,其中包含一个调用回调和延迟加载该类的函数)。那是2009年,以及这个功能是否已经在PHP的更高版本中删除了我不知道,但它似乎不适用于5.3.5
有没有办法做到这一点,或者您对我应该关注的其他模式有什么建议吗?
感谢。
哇!感谢所有的答案。我认为你们中有很多人认为这是一个可能的过早优化,或者更糟糕的是,根本不是优化是非常有效的,我将进行分析以检查我所解决的任何解决方案实际上是否有助于不伤害。 ... 现在正确阅读和消化你的所有想法。再次感谢。
答案 0 :(得分:6)
从PHP 5.4开始,你可以(re-)bind Anonymous Functions and Closures:
<?php
class Foo
{
private $bar = 1;
}
$getBar = function() { return $this->bar; };
$foo = new Foo;
$foo->getBar = $getBar->bindTo($foo, $foo);
echo call_user_func($foo->getBar); // prints "1"
有关Closure实现和潜在问题的讨论,请参阅https://wiki.php.net/rfc/closures/object-extension。
一般情况下,如果您发现您的类有很多长方法,请尝试将它们分解为较小的块。用简单的英语描述这些方法的用途。为每个“和”创建一个新方法并在那里移动代码。
另请参阅该类中的各种属性。如果其中一些在概念上一起进行,请考虑将它们变成自己的对象。将访问这些属性的任何方法移动到新对象以进行内聚。
我也有点质疑你想要在课堂上“懒惰加载”方法的动机。将它们放在那里没有性能上的复杂性,即使你不使用它们也是如此。如果这是用于性能优化,那么您可能正在从错误的一端接近它。
另一个选择是使用Traits或更简单的Composition。
答案 1 :(得分:4)
回调解决方案看起来非常难看 您可以使用合成模式和自动加载:
class MyClass
{
protected $logger;
function SomeFunction($arg)
{
$this->Logger()->write($arg);
}
function Logger()
{
if (empty($this->logger)) $this->Logger = new Logger(); //lazy initialization of method
return $this->logger;
}
}
但是,我必须说,所有这些只是微观优化,不要浪费你的时间。创建新对象和自动加载另一个文件(它使用磁盘)的时间比使用“大”方法简单初始化对象要大。
答案 2 :(得分:1)
我不知道只加载一部分类的(性能有效)方法。
我认为您需要将类的方法分成子类,并使用autoloading加载它们。
完成后,可以考虑做这样的事情:
class myMainClass
{
function bigFatMethod($argument, $argument2)
{
return mySubClass::bigFatMethod($this, $argument, $argument2);
// (pass $this if necessary)
}
}
这会在bigFatMethod()
内保持myMainClass
可调用,但在内部,因为您正在使用自动加载,只有在实际调用bigFatMethod()
时才会加载必要的代码。
显然,您需要重写bigFatMethod()
以便可以静态调用它而不是访问$this
,您必须让它访问在其第一个参数中传递的对象(您传递给它)父类中的$this
。
我自己从未这样做过 - 我倾向于将课程拆分为子课程,并单独解决这些问题 - 但我无法通过这种方式看到任何巨大的缺点。
如果你愿意,你甚至可以使用__call()
魔术方法抽象bigFatMethod()
,该方法会查找它必须加载的子类,执行该方法并返回结果。
答案 3 :(得分:1)
你的班级可能会尝试做太多。我建议尝试将其分成单独的服务。然后,您可以使用依赖注入容器(例如Pimple)来延迟加载实际使用的那些服务。
我建议不要滥用继承权。相反,你应该favor composition over inheritance。这使您的设计更清晰,代码库更易于维护。
答案 4 :(得分:1)
<?php
class BigClass
{
public function lazy()
{
return include 'lazy.func.php';
}
}
这应该有效并满足您的要求。我对它可能产生的副作用并没有太多考虑。
答案 5 :(得分:0)
只加载一部分课 - 这根本不可能。当你创建类的新实例时,它会初始化整个类,因此没有延迟加载你只需要的函数
答案 6 :(得分:0)
您可以编写一个包含所有基本功能的基类,然后使用继承来逐步添加更多专用功能,并且只在需要时使用继承类。
答案 7 :(得分:0)
您可以使用魔术类方法__get
动态加载属性,或使用魔术方法__call
来委托其他类/方法。当你需要初始化属性或方法等时,只有在访问属性或方法等时,这些才是很棒的。
奇怪的是,我最近在博客上谈到了这件事,因为我在我的一个项目中需要一个庞大的课程。这有点牵扯,但我试图简单地解释一下。它可能会给你一些指示。