gpt4 book ai didi

php - OO : Inheritance vs Service

转载 作者:可可西里 更新时间:2023-10-31 23:30:32 26 4
gpt4 key购买 nike

关闭。这个问题是opinion-based .它目前不接受答案。












想改善这个问题吗?更新问题,以便可以通过 editing this post 用事实和引文回答问题.

6年前关闭。




Improve this question



Class A
{
public function __construct(Foo $foo, Bar $bar, MyCustomType1 $mct)
{
//...
}
//...
public function getFooBarFunction()
{
$this->foo->aMethod();
$this->bar->anotherMethod();
//some other execution here
}
}

Class B
{
public function __construct(Foo $foo, Bar $bar, MyCustomType2 $mct)
{
//...
}
//...
public function getFooBarFunction()
{
$this->foo->aMethod();
$this->bar->anotherMethod();
//some other execution here (same of Class A)
}
}

Class C
{
public function __construct(Foo $foo, Bar $bar, MyCustomType3 $mct)
{
//...
}
//...
public function getFooBarFunction()
{
$this->foo->aMethod();
$this->bar->anotherMethod();
//some other execution here (same of Class B and Class A)
}
}

如您所见,此代码不遵守 DRY 原则。我很容易崩溃 getFooBarFunction()进入另一个类并使用该方法。

A) 创建一个 SuperClass 并迁移 getFooBarFunction()进去。我需要复制 __construct()也( $this-> 引用)。
优点
- 很容易做到
- 我可以为 MyCustomType 创建一个界面(s) 并将其用于构造以替代具体类
缺点
- 如果子类需要在构造阶段添加参数怎么办?
- 如果我不能分组怎么办 MyCustomType (s) 在同一个界面下?

B) 创建一个 SuperClass 并使用 setter 来“注入(inject)” FooBar对象
优点
- 也很容易
- 我不需要共享构造函数
缺点
- 如果我忘记注入(inject)参数怎么办?我是否需要向 SuperClass 添加额外的显式检查并引发异常?

C) 创建一个 SuperClass 并让 getFooBarFunction()接受 FooBar对象
优点
- 也很容易
- 我不需要共享构造函数
缺点
- 真的有必要,在那种情况下,继承?

D) 创建一个独立的类(服务?)并让 A , B , C实例化并直接使用

什么是最佳方法(或“最佳实践”),为什么?还有其他人吗?

更新

A 类、B 类和 C 类是一些互不共享任何信息的对象(它们代表一个 Room ,一个 Service ,一个 Supplement )。唯一的共同点是每个类都和i18n表有关系(每个类都有自己的表)。所以我的 getFooBarFunction()只是一个用于检索静态类型的函数(存储在某处,不重要),指示 i18n 文本的类型(标题、描述、短名称等)

UPDATE2 真实代码
private function getTextTypeNameEntity()
{
$text_type_repository = $this->getTextTypeRepository();
$text_type_name_id = $this->container->getParameter('foo_project.text_type.name');
$text_type_name = $text_type_repository->findOneById($text_type_name_id);

return $text_type_name;
}

这个函数是 getFooBarFunction()

最佳答案

更新 2 的答案

你说这个函数只通过一个唯一的 id 从存储库中获取文本。在不知道完整类的情况下,这听起来像是代码异味。一个类应该只做一件事,并且做好。当您实现不严格相关的功能时,您将类扩展到边界上。我会改变 getFooBarFunction仅提供文本 ID:

public function getTextId() {
return 'some-awesome-unique-text-id';
}

原帖

查看您提供的代码时,我只能看到一个不同之处,即 MyCustomType .我会输入提示一个共享接口(interface),它为每个可以调用的方法(接口(interface)基础)实现签名。这也适用于 FooBar类。通过使用接口(interface),您可以更轻松地交换实际的类实现。

你说:“如果我不能在同一个界面下对我的自定义类型进行分组怎么办?”。这很棘手,也是接口(interface)的难点之一。将接口(interface)视为契约。如果您更改了一个类的方法签名,但尝试使用它代替另一个类,您肯定会遇到错误。这也会使您的代码更难维护/阅读,因为您将尝试在所有地方处理边缘情况。尝试坚持使用界面。

你说:“如果我忘记注入(inject)参数怎么办?”。首先,这应该被视为错误/错误,您作为开发人员负责,抱歉:D

你后来说,“如果我需要在构造过程中传递另一个参数怎么办?”。对我来说,这听起来像是一个不同的类,应该这样对待。然后,如果您无论如何都需要另一个参数,则可以扩展此类并仅覆盖构造函数。类似于以下内容。
abstract class AbstractImplementation {

public function __construct(FooInterface $foo, BarInterface $bar, CustomInterface $custom) {

// Initialize properties.

}

/*
* This could also be declared abstract if each implementation
* is different.
*/
public function getFooBarFunction() {

// Perform basic actions

}

}

class ActualImplementation extends AbstractExample {

public function getFooBarFunction() {

// Perform specific actions

}

}

然后,如果您需要另一个参数,您可以这样做。这应该被视为一种边缘情况。
class ExtendedImplementation extends ActualImplementation {

public function __construct(Extra $extra, FooInterface $foo, BarInterface $bar, CustomInterface $custom) {

parent::__construct($foo, $bar, $custom);

$this->extra = $extra;

}

}

希望我的想法可以帮助你,快乐编码!

关于php - OO : Inheritance vs Service,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28452242/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com