什么时候在对象中使用工厂方法而不是factory类是一个好主意?
当前回答
GOF定义:
定义一个用于创建对象的接口,但是让子类来决定实例化哪个类。工厂方法允许类延迟实例化到子类。
一般例子:
public abstract class Factory<T> {
public abstract T instantiate(Supplier<? extends T> supplier);
}
具体类
public class SupplierFactory<T> extends Factory<T> {
@Override
public T instantiate(Supplier<? extends T> supplier) {
return supplier.get();
}
}
实现
public class Alpha implements BaseInterface {
@Override
public void doAction() {
System.out.println("The Alpha executed");
}
}
public class Beta implements BaseInterface {
@Override
public void doAction() {
System.out.println("The Beta executed");
}
}
public interface BaseInterface {
void doAction();
}
public class Main {
public static void main(String[] args) {
Factory<BaseInterface> secondFactory = new SupplierFactory<>();
secondFactory.instantiate(Beta::new).doAction();
secondFactory.instantiate(Alpha::new).doAction();
}
}
短暂的优势
您正在分离可以变化的代码和不变的代码(即,使用简单工厂模式的优点仍然存在)。这种技术可以帮助您轻松地维护代码。 你的代码不是紧密耦合的;因此,你可以随时在系统中添加新的类,如Lion、Beer等,而无需修改现有的体系结构。因此,您遵循了“修改封闭,扩展开放”的原则。
其他回答
假设你有不同的客户,他们有不同的偏好。有人需要大众、奥迪等等。有一样东西是共同的,那就是汽车。
为了让我们的客户满意,我们需要一个工厂。工厂只需要知道客户想要哪一辆车,并将其交付给客户。如果以后我们有另一辆车,我们可以很容易地扩大我们的停车场和工厂。
下面你可以看到一个例子(ABAP):
现在,我们将创建工厂的实例,并监听客户的愿望。
我们只用一个create()方法创建了三种不同的汽车。
结果:
如果你想让逻辑更清晰,程序更可扩展,工厂模式通常非常有用。
如果你想在使用方面创建一个不同的对象。它很有用。
public class factoryMethodPattern {
static String planName = "COMMERCIALPLAN";
static int units = 3;
public static void main(String args[]) {
GetPlanFactory planFactory = new GetPlanFactory();
Plan p = planFactory.getPlan(planName);
System.out.print("Bill amount for " + planName + " of " + units
+ " units is: ");
p.getRate();
p.calculateBill(units);
}
}
abstract class Plan {
protected double rate;
abstract void getRate();
public void calculateBill(int units) {
System.out.println(units * rate);
}
}
class DomesticPlan extends Plan {
// @override
public void getRate() {
rate = 3.50;
}
}
class CommercialPlan extends Plan {
// @override
public void getRate() {
rate = 7.50;
}
}
class InstitutionalPlan extends Plan {
// @override
public void getRate() {
rate = 5.50;
}
}
class GetPlanFactory {
// use getPlan method to get object of type Plan
public Plan getPlan(String planType) {
if (planType == null) {
return null;
}
if (planType.equalsIgnoreCase("DOMESTICPLAN")) {
return new DomesticPlan();
} else if (planType.equalsIgnoreCase("COMMERCIALPLAN")) {
return new CommercialPlan();
} else if (planType.equalsIgnoreCase("INSTITUTIONALPLAN")) {
return new InstitutionalPlan();
}
return null;
}
}
我个人认为单独的Factory类有意义的一种情况是,当您试图创建的最终对象依赖于其他几个对象时。例如,在PHP中:假设你有一个House对象,它又有一个Kitchen和一个LivingRoom对象,LivingRoom对象内部也有一个TV对象。
实现这一点的最简单方法是让每个对象在它们的construct方法上创建它们的子对象,但是如果属性是相对嵌套的,那么当您的House创建失败时,您可能会花一些时间试图隔离到底是什么失败了。
另一种方法是做以下事情(依赖注入,如果你喜欢这个花哨的术语):
$TVObj = new TV($param1, $param2, $param3);
$LivingroomObj = new LivingRoom($TVObj, $param1, $param2);
$KitchenroomObj = new Kitchen($param1, $param2);
$HouseObj = new House($LivingroomObj, $KitchenroomObj);
在这里,如果创建House的过程失败了,那么只有一个地方可以查看,但每次想要一个新House时都必须使用这个块,这非常不方便。进入工厂:
class HouseFactory {
public function create() {
$TVObj = new TV($param1, $param2, $param3);
$LivingroomObj = new LivingRoom($TVObj, $param1, $param2);
$KitchenroomObj = new Kitchen($param1, $param2);
$HouseObj = new House($LivingroomObj, $KitchenroomObj);
return $HouseObj;
}
}
$houseFactory = new HouseFactory();
$HouseObj = $houseFactory->create();
由于这里的工厂,创建House的过程是抽象的(因为当您只想创建一个House时,您不需要创建和设置每个依赖项),同时是集中的,这使得它更容易维护。使用单独的工厂是有益的还有其他原因(例如可测试性),但我发现这个特定的用例最好地说明了工厂类是如何有用的。
我简短的解释是,当我们没有足够的信息来创建一个具体的对象时,我们使用工厂模式。我们要么不知道依赖关系,要么不知道对象的类型。我们几乎总是不知道它们因为这是运行时的信息。
示例:我们知道我们必须创建一个车辆对象,但我们不知道它是飞行还是在地面上工作。
当您需要几个具有相同参数类型但具有不同行为的“构造函数”时,它们也很有用。