Php,如何实现一个完美不可变的构建器类?

发布于 2025-01-09 05:54:01 字数 1747 浏览 0 评论 0原文

正如我所见,不变性和构建器模式是矛盾的。你无法同时实现同样的目标。

final class Builder
{
    private array $data = [];

    public function setName(string $v) : self
    {
        $this->data['name'] = $v;
        return $this;
    }

    public function setId(int $v) : self
    {
        $this->data['id'] = $v;
        return $this;
    }

    public function toArray() : array
    {
        return $this->data;
    }
}

$builder = new Builder();
$builder->setName('test')->setId(3);

这样做很简单,但违反了不变性:$this->data 更改了两次。 当然有一个小解决方法,闻起来像“木铁环”:

final class Builder
{
    readonly private string $name;
    readonly private int $id;

    public function setName(string $v) : self
    {
        $this->name = $v;
        return $this;
    }

    public function setId(int $v) : self
    {
        $this->id = $v;
        return $this;
    }

    public function toArray() : array
    {
        return ['name' => $name, 'id' => $id];
    }
}

$builder = new Builder();
$builder->setName('test')->setId(5);

这理论上实现了不变性,但仍然有臭味。定义:“

不可变类定义的对象一旦创建就永远不会改变 他们的价值

”,但这并不完全适用于这里。Builder 创建后,值在构造后发生变化。 当然是最终的解决方案:

final class Builder
{
    readonly private string $name;
    readonly private int $id;

    public function __construct(string $name, int $id)
    {
        $this->name = $name;
        $this->id = $v;
    }

    public function toArray() : array
    {
        return ['name' => $name, 'id' => $id];
    }
}

但这就是为什么使用 Builder 而不是这个。如果有10个参数怎么办?什么是不是全部都需要的? 不管怎样,在这种情况下有必要有不可变的类吗? Builder 对象本身不会被使用,只会使用它的 ->toArray() 结果!

as I see, the immutability and builder-pattern are paradox. You cannot achieve the same at the same time.

final class Builder
{
    private array $data = [];

    public function setName(string $v) : self
    {
        $this->data['name'] = $v;
        return $this;
    }

    public function setId(int $v) : self
    {
        $this->data['id'] = $v;
        return $this;
    }

    public function toArray() : array
    {
        return $this->data;
    }
}

$builder = new Builder();
$builder->setName('test')->setId(3);

it's simple to do, but violates the immutability: $this->data changes two times.
Of course there is a little workaround, which smells like "wooden iron ring":

final class Builder
{
    readonly private string $name;
    readonly private int $id;

    public function setName(string $v) : self
    {
        $this->name = $v;
        return $this;
    }

    public function setId(int $v) : self
    {
        $this->id = $v;
        return $this;
    }

    public function toArray() : array
    {
        return ['name' => $name, 'id' => $id];
    }
}

$builder = new Builder();
$builder->setName('test')->setId(5);

this theoretically implements the immutability, but still smelly. The definition: "

immutable classes define objects which, once created, never change
their value

" but this not preciselly applies here. After Builder created, values changed after constructed.
Of course, the ultimate solution:

final class Builder
{
    readonly private string $name;
    readonly private int $id;

    public function __construct(string $name, int $id)
    {
        $this->name = $name;
        $this->id = $v;
    }

    public function toArray() : array
    {
        return ['name' => $name, 'id' => $id];
    }
}

but this is why Builder used instead of this. What if there are 10 parameters? What is not all is required?
Anyway, is it neccessary to have immutable class in case like that? The Builder object itself won't be used, only its ->toArray() result!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

待天淡蓝洁白时 2025-01-16 05:54:01

这听起来非常理论化,但没有真正考虑为什么创建这些理论概念。为什么我们要使用不可变对象?

我可以列举一些优点:

  • 它们更高效,因为它们只是存在,无需进行任何计算。
  • 由于它们不会改变,因此可以在程序的不同部分之间共享它们,而无需检查其内容。
  • 它们无法更改,如果没有适当的检查,这始终可能会带来安全风险。
  • 它们通常非常简单且易于理解,这就是编程的主要内容。

然而,对象不必是不可变的。更多时候,对象是可变的,这很好。如果没有可变对象,您的程序将不会执行任何操作。

不要为这些理论概念而烦恼。它们的存在是为了帮助您了解自己在做什么以及后果是什么,但它们并不是铁定的法律。只要你知道自己在做什么,你就可以打破它们并忽略它们。

This sound all very theoretical, without actually considering why these theoretical concepts were created. Why would we want to use immutable objects?

I can name a few advantages:

  • They are more efficient because they just exist, without having to do any computation.
  • Since they don't change, they can be shared between different sections of a program, without having to check their content.
  • They can't change, which could always be a security risk without the proper checks.
  • They are often quite simple and easy to understand, and that's what programming is mostly about.

However, objects don't have to be immutable. More often objects are mutable, and that's fine. Your program would do nothing without mutable objects.

Don't fret over these theoretical concepts. They exists to help you understand what you're doing and what the consequences are, but they are not ironclad laws. You are allowed to break them and ignore them, as long as you know what you're doing.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文