OOP (php) 在另一个 class 中实例化 class
OOP (php) instantiating class within another class
不确定我是否选择了正确的标题。但无论如何。
我必须支持和开发现有的项目。
它建立在 OOP 之上。
我有订单、产品等模型。它们经常用于代码中。
每个模型都绑定到相应的 table。
客户想要将一种新型客户集成到系统中。
这类客户拥有不同的关联数据,并订购完全不同种类的产品。所以订单看起来会有所不同。
我决定不把旧的秩序和新的秩序混在一起。起初我把它们放在不同的 tables 中,为了不破坏工作系统,并为它们创建了不同的 classes。
现在我有模型 Order.php 和 OrderNew.php、Product.php 和 ProductNew.php 等等。
我有全局设置 object,其中 属性 包含我需要实例化的 class 类型。
现在我已经搞砸了很多代码:
if ($global->object->isNewKindOfCustomer()) {
$product = new ProductNew;
} else {
$product = new Product;
}
但是在很多地方这样做我强烈地觉得我做错了很多事情。
所以我的第一个想法是应该由 class 产品决定什么产品应该被实例化。
如果我可以转到旧产品 class 并在其构造函数中执行以下操作,那就太完美了:
Class Product {
__construct() {
if ($global->object->isNewKindOfCustomer()) {
$product = new ProductNew;
} else {
$product = new Product();
}
}
}
此外,我将从 Product 继承 ProductNew 并重新定义所有需要更改的方法。类似于:
Class ProductNew extends Product {
public methodsDefinedInProductButInNeedToBeChangedForProductNew (){
}
}
但问题是我没能在 PHP 中找到一个合理的方法,而且它仍然闻起来不太好。但比第一种方法好得多(至少对我而言)。
第三个想法是,我现在将只创建 ProductNew class,还要创建 ProductOld class(不存在但我得到的本身)。
我会将所有代码从当前产品 class 移动到 ProductOld。
所以我当前的 Product class 将没有方法。它会变空。
此外,ProductNew 将从 ProductOld 继承。
有了这样的方案我根本不会去碰整个系统的代码。
在代码中的任何地方,assignemnts 都将具有以下外观
$product = new Product
在内部,我需要以某种方式管理将在 Product 构造函数中创建的 object。
第四个想法是,我将首先创建一个通用的 class 并将其命名为例如产品通用。它将具有与 ProductNew 和 ProductOld classes 相关的方法。它们都将扩展 ProductGeneral。在 Product 内部,只有正确的 class 会根据当前用户的角色被实例化。虽然我不确定 ProductGeneral 是否有必要....
仍然不知道如何在产品 class 中替换它。我记得它在 C++ 中被称为类似动态绑定的东西。
有没有更好的解决方案来解决这个问题?我错过了什么吗?
对不起,文字太长了,我尽量让它尽可能短。
您可能想要一个具有所有基本功能的 Product
class,一个具有特定功能的 ProductOld
class,以及一个 ProductNew
具有特定于 class 的功能。此外,ProductFactory
将 return 提供给您 class 您需要的产品。
在没有看到代码的情况下,很难说最好是按上面的方法做,还是只 extend
Product
class 和 ProductFactory
.
哦不:(完全错误。
Class Product {
__construct() {
if ($global->object->isNewKindOfCustomer()) {
$product = new ProductNew;
} else {
$product = new Product();
}
}
}
你从哪里得到的$global
?它不在您的构造函数中。您无法从任何地方获得实例。这会产生 untestable code.
您正在寻找 factory pattern。
if ($global->object->isNewKindOfCustomer()) {
$product = new ProductNew;
} else {
$product = new Product;
}
But doing so in many places I got strong feeling that I do something very VERY wrong.
我同意。这就是覆盖的目的。
Assimung $global->object
是 Customer
类型,添加一个方法 newProduct
可以根据需要重写:
class Customer
{
public function newProduct()
{
return new Product();
}
}
class CustomerNew extends Customer
{
public function newProduct()
{
return new ProductNew();
}
}
那么你必须检查一次你是在处理新的客户类型还是旧的客户类型(在实例化 Customer
或 CustomerNew
时),并且永远不会再检查一次。
这基本上就是 "factory pattern",只是不是单独的 class.
此外,我建议您不要使用 "normal" 旧的 class 和新的覆盖 class,而是将所有共同点移到新的基础 class , 喜欢
abstract class CustomerBase
{
// Define here all methods that Customer and CustomerNew have in common
// And make "implementation-dependent" methods abstract:
public abstract function newProduct();
}
class Customer extends CustomerBase
{
public function newProduct()
{
return new Product();
}
}
class CustomerNew extends CustomerBase
{
public function newProduct()
{
return new ProductNew();
}
}
这将是一个 "cleaner" 实现(语义上),您仍然不必将代码中的每个 Customer
替换为 CustomerOld
或其他内容。
我建议你用 Product
做同样的事情,而不是仅仅覆盖 "default"
中的方法
不确定我是否选择了正确的标题。但无论如何。
我必须支持和开发现有的项目。
它建立在 OOP 之上。
我有订单、产品等模型。它们经常用于代码中。
每个模型都绑定到相应的 table。
客户想要将一种新型客户集成到系统中。 这类客户拥有不同的关联数据,并订购完全不同种类的产品。所以订单看起来会有所不同。
我决定不把旧的秩序和新的秩序混在一起。起初我把它们放在不同的 tables 中,为了不破坏工作系统,并为它们创建了不同的 classes。
现在我有模型 Order.php 和 OrderNew.php、Product.php 和 ProductNew.php 等等。
我有全局设置 object,其中 属性 包含我需要实例化的 class 类型。
现在我已经搞砸了很多代码:
if ($global->object->isNewKindOfCustomer()) {
$product = new ProductNew;
} else {
$product = new Product;
}
但是在很多地方这样做我强烈地觉得我做错了很多事情。
所以我的第一个想法是应该由 class 产品决定什么产品应该被实例化。
如果我可以转到旧产品 class 并在其构造函数中执行以下操作,那就太完美了:
Class Product {
__construct() {
if ($global->object->isNewKindOfCustomer()) {
$product = new ProductNew;
} else {
$product = new Product();
}
}
}
此外,我将从 Product 继承 ProductNew 并重新定义所有需要更改的方法。类似于:
Class ProductNew extends Product {
public methodsDefinedInProductButInNeedToBeChangedForProductNew (){
}
}
但问题是我没能在 PHP 中找到一个合理的方法,而且它仍然闻起来不太好。但比第一种方法好得多(至少对我而言)。
第三个想法是,我现在将只创建 ProductNew class,还要创建 ProductOld class(不存在但我得到的本身)。
我会将所有代码从当前产品 class 移动到 ProductOld。 所以我当前的 Product class 将没有方法。它会变空。 此外,ProductNew 将从 ProductOld 继承。
有了这样的方案我根本不会去碰整个系统的代码。 在代码中的任何地方,assignemnts 都将具有以下外观
$product = new Product
在内部,我需要以某种方式管理将在 Product 构造函数中创建的 object。
第四个想法是,我将首先创建一个通用的 class 并将其命名为例如产品通用。它将具有与 ProductNew 和 ProductOld classes 相关的方法。它们都将扩展 ProductGeneral。在 Product 内部,只有正确的 class 会根据当前用户的角色被实例化。虽然我不确定 ProductGeneral 是否有必要....
仍然不知道如何在产品 class 中替换它。我记得它在 C++ 中被称为类似动态绑定的东西。
有没有更好的解决方案来解决这个问题?我错过了什么吗?
对不起,文字太长了,我尽量让它尽可能短。
您可能想要一个具有所有基本功能的 Product
class,一个具有特定功能的 ProductOld
class,以及一个 ProductNew
具有特定于 class 的功能。此外,ProductFactory
将 return 提供给您 class 您需要的产品。
在没有看到代码的情况下,很难说最好是按上面的方法做,还是只 extend
Product
class 和 ProductFactory
.
哦不:(完全错误。
Class Product {
__construct() {
if ($global->object->isNewKindOfCustomer()) {
$product = new ProductNew;
} else {
$product = new Product();
}
}
}
你从哪里得到的$global
?它不在您的构造函数中。您无法从任何地方获得实例。这会产生 untestable code.
您正在寻找 factory pattern。
if ($global->object->isNewKindOfCustomer()) { $product = new ProductNew; } else { $product = new Product; }
But doing so in many places I got strong feeling that I do something very VERY wrong.
我同意。这就是覆盖的目的。
Assimung $global->object
是 Customer
类型,添加一个方法 newProduct
可以根据需要重写:
class Customer
{
public function newProduct()
{
return new Product();
}
}
class CustomerNew extends Customer
{
public function newProduct()
{
return new ProductNew();
}
}
那么你必须检查一次你是在处理新的客户类型还是旧的客户类型(在实例化 Customer
或 CustomerNew
时),并且永远不会再检查一次。
这基本上就是 "factory pattern",只是不是单独的 class.
此外,我建议您不要使用 "normal" 旧的 class 和新的覆盖 class,而是将所有共同点移到新的基础 class , 喜欢
abstract class CustomerBase
{
// Define here all methods that Customer and CustomerNew have in common
// And make "implementation-dependent" methods abstract:
public abstract function newProduct();
}
class Customer extends CustomerBase
{
public function newProduct()
{
return new Product();
}
}
class CustomerNew extends CustomerBase
{
public function newProduct()
{
return new ProductNew();
}
}
这将是一个 "cleaner" 实现(语义上),您仍然不必将代码中的每个 Customer
替换为 CustomerOld
或其他内容。
我建议你用 Product
做同样的事情,而不是仅仅覆盖 "default"