我注意到一些ORM实现,其中数据库搜索工作作为对象类的静态方法发生,如MongooseJS中那样:
var myCar = new Car({ name: 'MyCar' });
Car.find({ name: /MyCar/ }, callback)
Rails和Laravel做了类似的事情。作为一种代表汽车的方式,这对其他人来说是否有点奇怪?对我来说,find()更像是工厂方法,应该看起来像
var myCar = new Car({ name: 'MyCar' });
CarFactory.find({ name: /MyCar/ }, callback)
或者甚至
var myCar = CarFactory.createCar({ name: 'MyCar' });
CarFactory.find({ name: /MyCar/ }, callback)
尽管find()本质上是Car 类上的一个静态方法(与对象本身相对),但对我来说仍然感觉有点像汽车知道所有的其他车。这对其他人来说是不是很奇怪,还是我在想这个?
谢谢!
答案 0 :(得分:1)
我必须将这个答案分成两部分。第一部分是何时使用工厂,第二部分是ORM的“幕后”。但在我开始之前:这很大程度上取决于我自己的经历。你应该总是自己决定什么最适合你的项目(在这种情况下,使用工厂模式是有意义的,而不是等等)。
何时使用工厂
我经常将工厂视为生成具有依赖关系的对象的方法,这些对象在我创建它时并不知道,或者作为生成我经常需要的对象的简写方式。
例如,假设我们有一个工厂方法可以找到所有“快速”汽车。
class CarFactory {
public static function getFastCars()
{
return Car::where('max_speed', '>', '180')->get();
}
}
现在,当我们将这种方法称为$cars = CarFactory::getFastCars();
时,我不必知道汽车必须要多快才能快速。但是,在您的示例中,您知道汽车的名称,这是ORM找到您的汽车的唯一条件。我认为工厂会让你的代码变得更加复杂。
工厂的另一个用例可能是生成汽车的特定类型。让我们想象一下,我们正在建立一个汽车租赁服务,其中我们可以输入我们想要开车的位置,服务告诉我们哪辆车最适合我们的旅程。这就是工厂派上用场的地方:
/**
* Car classes
*/
class Car {
public function __toString()
{
return 'basic car';
}
}
class SportsCar extends Car {
public function __toString()
{
return 'sports car';
}
}
class OffroadCar extends Car {
public function __toString()
{
return 'off-road car';
}
}
/**
* The factory
*/
class CarFactory {
public static function carForLocation($location)
{
$car = null;
switch ($location)
{
case 'racetrack':
$car = new SportsCar();
break;
case 'hills':
$car = new OffroadCar();
break;
default:
$car = new Car();
}
return $car;
}
}
/**
* Generating the car based on a location
*/
$car = CarFactory::carForLocation('racetrack');
echo "The type of car best for your journey is a {$car}.";
// Output: The type of car best for your journey is a sports car.
关于ORM
在我的例子中,工厂了解所有汽车。然而,ORM或模型在这里是特定的,不保留任何关于任何汽车的信息(可以说是处于“原始”状态)。在幕后,当您调用Car.find({name: /MyCar/})
时,ORM将通过它所依赖的查询构建器从数据库中获取汽车信息。然后,您的汽车实例会将该信息保存在其属性中。
这个答案在某些方面可能是肤浅的(尤其是ORM部分),但我希望无论如何我都可以帮助你。