sdboyer/frozone

冻结并锁定对象。还能让你看起来更像塞缪尔·L·杰克逊,增加23%。

1.0.2 2014-02-06 17:59 UTC

This package is not auto-updated.

Last update: 2024-09-14 14:40:00 UTC


README

Frozone stops writes like a boss Build Status Coverage Status Latest Stable Version

管理状态很糟糕。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 应用程序出现,某些类型的状态正在有效地封装在对象中。在这些情况下,值得管理。