我有以下名为Customer的PHP类,函数 create(),它将客户的数据存储到数据库中:
class Customer
{
public $createdby;
public $cname;
public function create()
{
...
}
}
因为我需要在一个循环中存储更多的客户,其中只有名称($ cname变量)发生变化(为了简单起见,因为变量创建的变量对于这个循环中的所有创建的客户都是相同的),问题就出现了(和为什么)更好的做法;
方法A )重用同一个Customer对象,其中只更改变量的变量:
$Customer=new Customer();
$Customer->createdby='somebody';
foreach($cnames as $cname)
{
$Customer->cname=$cname;
$Customer->create();
}
方法B )设置新的Customer对象并为每个特定的创建设置所有变量,如:
foreach($cnames as $cname)
{
$Customer=new Customer();
$Customer->createdby='somebody';
$Customer->cname=$cname;
$Customer->create();
}
如果我想创建一个Customer对象数组,当然,我必须使用第二种方法。但这不是那种情况。我没有看到第一原则的任何缺点,重用现有的对象将更多的客户存储到数据库中,但也许我错了。所以我问以下是什么是更好的做法以及为什么!
答案 0 :(得分:3)
静态实例化程序
首先 - 如果该方法是实例化方法,逻辑上必须是static
(因为在实例化之前没有对象上下文)。实例化方法的情况是静态方法的合法用例之一。因此,您的常规create()
方法是错误的,因为它在对象上下文上运行。当然,您可以使用类__construct()
魔术方法 - 如果您确定实例化逻辑将始终相同。
使用工厂
另一种方法是使用一些工厂类来使用给定数据实例化对象 - 因此,实现Factory模式。在你的情况下可能是这样的:
class CustomerFactory
{
public function createByNames($name, $createdBy)
{
$customer = new Customer();
$customer->setName($name);
$customer->setCreatedBy($createdBy);
return $customer;
}
}
这里的好处是 - 您的原始类可能会摆脱实例化逻辑,工厂将负责根据业务规则创建有效的实体。完整性。例如,您可以为实例化添加一些验证,并将某些验证器作为dependency传递:
class CustomerFactory
{
public function createByRawData(CustomerValidator $validator, array $customerData)
{
if(!$validator->check($customerData))
{
//or use some namespace, which I omit here to simplify case:
throw new CustomerInstantiationException('Creation error '.$validator->getErrorMessage());
}
$customer = new Customer();
$customer->setData($customerData);
return $customer;
}
}
正如您所看到的,这种方法如果更加灵活和可扩展 - 并且不需要修改Customer
类 - 因为逻辑现在属于工厂。
收集实例化
在简单的情况下,您可以使用工厂来实例化多个对象。您可以返回此类对象的数组,也可以添加特殊的类似集合的实体(其行为类似于集合,因此,最有可能扩展为Iterator)等接口。选择是你的 - 但我推荐第二个 - 再次,因为你能够在不改变工厂代码的情况下扩展你的逻辑(只有你的收集行为,以后可以用某些东西扩展)。
所以,回答你关于重新使用的问题 - 如果需要不同的实例,你需要决定。如果它们是,并且意图是与多个实例交互 - 那么您应该单独创建它们。并且,如果它们的行为类似于某种集合 - 那么好主意就是创建自定义集合类(它将实现Iterator或一些自定义集合接口) - 或者至少使用这样的对象数组。如果需要收集,那么我建议将实例化逻辑放在单独的工厂中,就像我上面描述的那样。
当您重复使用同一个对象时,您可以'显然,只有一个实体,它正在改变它的状态。如果这是你的逻辑的正确反映(即:你真的只有一个客户),那么你可以使用它。但是,如果您的客户在逻辑上是不同的实体,那么这是错误的方法,因为在您重新编写相同的对象后,您将无法对它们进行操作。
对象是您的业务实体反映,其行为是业务逻辑反射
答案 1 :(得分:0)
似乎两种方法都是平等的,但我更喜欢第二种方法。这将带来一些潜在的麻烦,与create()
方法的任何内部细节相关联(例如,如果beforeCreate()
对象不包含它,它可能会在某些Customer
方法中生成一些唯一的哈希值)。