Php 哄骗式
我在php中有一个类,它与chaining方法一起工作,但问题是我想以某种顺序链接这些方法Php 哄骗式,php,design-patterns,chaining,object-oriented-analysis,Php,Design Patterns,Chaining,Object Oriented Analysis,我在php中有一个类,它与chaining方法一起工作,但问题是我想以某种顺序链接这些方法 class Chain { public function foo () { return $this; } public function bar () { return $this; } public function some () { return $this; } } 因此,如果我使用这个类,那么我可以用9种不同的方式链接这个方法(3个元素的所有
class Chain {
public function foo () {
return $this;
}
public function bar () {
return $this;
}
public function some () {
return $this;
}
}
因此,如果我使用这个类,那么我可以用9种不同的方式链接这个方法(3个元素的所有可能组合)
但是,如果我确定方法some
总是必须在foo
或bar
之后链接,而不是以其他方式链接,会发生什么
$chain = new Chain();
$chain->foo->bar(); //works; i.e: the method some is optional
$chain->foo()->bar()->some(); //works
$chain->bar()->foo()->some(); //works
$chain->some()->bar()->foo(); //throws an exception
我想我可以设置布尔值,比如:当调用方法foo
或bar
时,我将某个变量的值设置为true
,当开发人员调用some
函数时,如果该变量是false
,则抛出异常,否则允许继续
但我需要一些更优雅的东西,比如模式或内置解决方案
还有另一种方法吗?强制呼叫者按照特定的呼叫顺序进行呼叫,就像结束本身一样,几乎没有任何用处。假设您真正感兴趣的是在调用
some()
时确保对象的状态是有效的,如果不是,则抛出异常。在这种情况下,是的,您将检查对象状态的某些指示器,并在该状态不满足可调用的some()
要求时引发异常。作为一个具体例子:
$api = new SomeAPI;
$api->setUserID($id);
$api->setSecretKey($secret);
$api->call('something');
这里的call()
将检查用户id和访问密钥是否已设置,否则它将无法完成其工作。这些调用是否链接是不相关的,只是一个语法细节
或者,您可以从方法中返回其他(子)类的某些对象,如果某些条件尚未满足,则在物理上无法对这些对象调用某些方法:
public function bar() {
if ($this->foo) {
return new SubFoo($this->foo);
} else {
return new SubBar;
}
}
不过,这可能过于复杂。我想象的这个非常粗糙的示例在每个方法中仍然会有一些代码行
<?php
class Chain {
private $_register = array();
public function foo () {
$this->register(__METHOD__);
return $this;
}
public function bar () {
$this->register(__METHOD__);
return $this;
}
public function some () {;
$this->verify('foo'); // foo() should be called before some();
$this->register(__METHOD__);
echo 'it\'s ok';
return $this;
}
public function verify($method) {
if(array_key_exists($method, $this->_register) && $this->_register[$method] == true) {
return true;
}
else {
throw new Exception('Some exception');
}
}
public function register($method) {
$method = str_replace(__CLASS__.'::', '', $method);
$this->_register[$method] = true;
}
}
致命错误:未捕获异常“exception”,消息为“Some”
“例外”在
没关系
这里的问题是我们建立了一个“公约”。您需要将\uuuu方法\uuuu
传递给register函数,这样在它替换类名之后,它将只在数组中添加方法名。因此,稍后,在需要验证在此之前是否调用了一个或多个函数的函数中,需要使用方法名称作为字符串,即$this->verify('foo')代码>
当然,如果您正在验证某个方法或smth其他方法,您可以在不使用strpos()
剥离和测试的情况下播放不同的场景,或者在方法名称后添加()
,以便于识别
但至少它会让你不用为每种方法制作不同的变量来填充
function foo() {
$this->_foo = true;
return $this;
}
function bar() {
$this->_bar = true;
return $this;
}
如果您不想调用bar()
如果以前没有调用foo()
,那么除了检查返回值之外没有其他方法。您可以创建一个代理方法(包装器),该方法可以完成所有工作,只需在bar()
中调用它,并指向paramfoo()
$chain = new Chain();
$chain->foo()->some()->foo(); // ok
function foo() {
$this->_foo = true;
return $this;
}
function bar() {
$this->_bar = true;
return $this;
}