如果我有Car
这样的课程:
class Car
{
/**
* @var string $model
*/
private $model;
/**
* Makes a new car based on a model
*
* @param string $model Initializes the model
*/
public function __construct($model) {
$this->model = $model;
}
/**
* Gets the car model
*
* @return string The model
*/
public function getModel() {
return $this->model;
}
}
这样CarValidator
:
class CarValidator
{
public function isValidated(Car $car) {
if (empty($car->getModel())) {
return false;
}
return true;
}
}
我的用法是这样的:
$bmw = new Car('bmw');
如何在实例化之前验证我的宝马汽车?
答案 0 :(得分:0)
我认为你有两个选择。
CarValidator
以在施工后验证汽车。这意味着验证是独立的(这似乎是你重视的东西),但意味着汽车可以建立在无效状态。如果验证是上下文的并且您的汽车被重复使用并且“有效”意味着某个地方有不同的东西,那么这可能没问题。其中哪一个最适用我认为从根本上说,它归结为在您的情况下“有效”以及有效性是否普遍适用。事实可能意味着两者兼而有之。
例如,对于所有汽车而言,拥有空模型可能无效,但目前某些模型颜色组合无效。在这种情况下,如果有人试图创建一个具有模型空字符串的汽车,那么您的汽车构造函数将抛出异常,因为这永远不会有效。
您的验证员可能会在施工后检查汽车是否有效,以确保您当前存在指定的型号/颜色组合。这些规则可能会发生变化,因此更适用于外部验证(您可能在某些国家/地区使用不同的可接受模型,或者根据其他一些因素使用不同的验证规则)。这些可以存在于您的CarValidator
班级中。
你的对象的任何基本不变量,你的程序的某些部分将依赖它(比如模型不为空的事实,应该由对象本身验证和强制执行,因为这些不是'业务规则'本身但是系统的不变量。
我可能会选择:
public class CarFactory
{
private ICarValidator validator;
public CarFactory(ICarValidator validator){ this.validator=validator;}
public Car Create(string model)
{
Car car = new Car(model);
if (validator.IsValid(car))
return car;
throw new InvalidCarException(car);
}
}
public Car
{
private string model;
public Car(string model)
{
if (model=="")
throw new EmptyModelException();
this.model=model;
}
}
这使您可以从业务逻辑(封装在Car
中)中分离出不变量(由CarValidator
强制执行),并禁止用户获取无效的汽车实例。