sdboyer / frozone
冻结并锁定对象。还能让你看起来更像塞缪尔·L·杰克逊,增加23%。
1.0.2
2014-02-06 17:59 UTC
Requires
- php: >=5.4
Requires (Dev)
- phpunit/phpunit: 3.7.*
- satooshi/php-coveralls: 0.6.*
This package is not auto-updated.
Last update: 2024-09-14 14:40:00 UTC
README
管理状态很糟糕。Frozone 是一套简单的接口和特性(因此,PHP >=5.4),它实现了一些模式来简化操作。它简化了两种情况
- 冻结,即将具有可变状态的对象不可逆地锁定,使其状态无法进一步修改(从外部)。
- 锁定,即使用密钥锁定具有可变状态的对象,该状态无法修改,直到提供相同的密钥解锁。
冻结
冻结是一个单向操作,通过调用 freeze()
方法启动。
use Frozone\Freezable; use Frozone\FreezableTrait; class Counter implements Freezable { use FreezableTrait; protected $callcount = 0; public function incrementAndEcho() { $this->attemptWrite(); // or $this->attemptWriteWithMethod(__METHOD__); // or $this->attemptWriteWithMessage('What the exception will say if it's frozen'); // now, your method's state-changing logic. echo ++$this->callcount; } public function justEcho() { echo $this->callcount; } } $counter = new Counter(); $counter->isFrozen(); // return FALSE $counter->incrementAndEcho(); // prints '1' $counter->freeze(); $counter->isFrozen(); // return TRUE $counter->justEcho(); // prints '1' $counter->incrementAndEcho(); // throws FrozenObjectException
锁定
锁定是一个可逆操作,通过调用带有密钥的 lock()
方法启动,并通过使用相同密钥的 unlock()
方法反转。
如果你需要将可变对象发送到其他代码,但又想限制在该上下文中对象的修改,这非常有用。
use Frozone\Lockable; use Frozone\LockableTrait; class Counter implements Lockable { use LockableTrait; protected $callcount = 0; public function incrementAndEcho() { $this->attemptWrite(); // or $this->attemptWriteWithMethod(__METHOD__); // or $this->attemptWriteWithMessage('What the exception will say if it's frozen'); // now, your method's state-changing logic. echo ++$this->callcount; } public function justEcho() { echo $this->callcount; } } $counter = new Counter(); $counter->isLocked(); // return FALSE $counter->incrementAndEcho(); // prints '1' $key = mt_rand(1, 10000); // Use a key appropriate for your use case $counter->lock($key); $counter->isLocked(); // return TRUE $counter->justEcho(); // prints '1' $counter->incrementAndEcho(); // throws LockedObjectException $counter->unlock('foo'); // throws LockedObjectException; wrong key $counter->lock('foo'); // throws LockedObjectException; already locked $counter->unlock($key); $counter->isLocked(); // return FALSE $counter->incrementAndEcho(); // prints '2'
常见问题解答
反射可以改变 PHP 对象状态,无论可见性如何。这不会使这个功能毫无意义吗?
在纯粹的函数式层面,这绝对是。
在 API 设计层面,即使调用代码可以覆盖 Frozone 提供的保护,如果你的对象在特定上下文/某个特定点后不应该被修改,仍然最好是向客户端代码提供明确的反馈,说明你提供的契约。
在 PHP 中管理对象状态真的值得吗?
在许多旧的 PHP 应用程序中,并不是。由于在 PHP 应用程序的执行环境中,状态通常在每个请求中从头开始构建,对象状态通常没有太多意义。但是,随着越来越多的现代 PHP 应用程序出现,某些类型的状态正在有效地封装在对象中。在这些情况下,值得管理。