我正在用Java实现工厂设计模式

SOP*_*SOP 5 java design-patterns

我正在用Java实现工厂设计模式,我想在抽象类中保留一个重载方法。它会违反工厂模式概念吗?还是请提出这是否是实施Factory设计模式的正确方法?

abstract class A{
    void meth(int a);
    void meth(int a,int b);
}

class Factory{
    public static A factoryMethod(int a){
         if(a==1){
            return new Ob1();
        }else{
            return new Ob2();
        }
    }
}

class Ob1 extends A{

void meth(int a){}
void meth(int a,int b){}
}
Run Code Online (Sandbox Code Playgroud)

Edw*_*uck 4

要实施Factory Pattern第一个,您需要考虑Factory将产生什么。让我们生产Vehicles.

public VehicleFactory {
   public Vehicle newVehicle(String type) {
      ...
   }
}
Run Code Online (Sandbox Code Playgroud)

它将Vehicles根据下面的类层次结构生成。

public interface Vehicle {
   public List<Door> getDoors();
}

public class Motorcycle implements Vehicle {
   public List<Door> getDoors() {
       return Collections.<Door>emptyList();
   }
}

public class SportsCar implements Vehicle {
   public List<Door> getDoors() {
       return Collections.<Door>unmodifiableList(Arrays.asList(new Door("driver"), new Door("passenger"));
   }
}

public class Hatchback implements Vehicle {
       public List<Door> getDoors() {
       return Collections.<Door>unmodifiableList(Arrays.asList(new Door("driver"), new Door("passenger"), new Door("back"));
   }
}
Run Code Online (Sandbox Code Playgroud)

那么你的VehicleFactory方法newVehicle(...)可能看起来像

public Vehicle newVehicle(String type) {
    if ("motorcycle".equals(type)) { return new Motorcycle(); }
    if ("sports car".equals(type)) { return new SportsCar(); }
    if ("hatchback".equals(type)) { return new Hatchback(); }
    return null;
}
Run Code Online (Sandbox Code Playgroud)

现在的主要问题是“你为什么要这样做?”

有时您需要一个漂亮干净的界面来构建许多相关项目。您为相关项目提供一个接口和一个工厂来构建它们。这使得使用这部分软件的人可以简单地引入 Interface 类和 ItemFactory。他们看不到单独的细节,这简化了他们的代码。

由于您在上面的代码中隐藏了所有内容的实现细节Vehicles,因此如果您遇到编程错误(或想要添加某些内容),您可以修复其中一个Vehicles(或添加新的Vehicle)到工厂并重新发布库(JAR 文件)包含VehicleFactory.

你知道其他人已经在使用这些VehicleFactory方法,所以你不必担心他们的代码在编译时被破坏,而且除非你不小心,你还可以确保它在运行时可以工作。

这并不等于说行为不会改变。新的实现Vehicle将被返回,希望嵌入的错误更少。另外,由于他们没有要求“新车”,您可能已经添加了他们不会看到它们,直到他们打电话newVehicle("station wagon")或类似的事情。

此外,您还可以更改它们的Vehicles构建方式。例如,如果您后来决定不想要一个简单的“只需一次构建它”的实现风格,您可以像这样更改 'newVehicle(...)'

 public Vehicle newVehicle(String type) {
    Chassis chassis;
    if ("motorcycle".equals(type)) {
       chassis = new TwoWheelChassis();
    } else {
       chassis = new FourWheelChassis();
    }
    return new ComponentVehicle(chassis, getDoorCount(type));
 }
Run Code Online (Sandbox Code Playgroud)

其中ComponentVehicle实现Vehicle并且由于某种原因需要一个显式Chassis对象。

--- 更新看到评论中的“方法数量”问题 ---

AFactory pattern实际上并不涉及方法的数量,而是涉及一种能够从一个或多个具体事物构建抽象事物的方法。

所以在上面的例子中,我可以

public VehicleFactory {
    public Vehicle newVehicle(String type) { ... }
    public Vehicle newRedVehicle(String type) { ... }
    public Vehicle newBlackVehicle(String type) { ... } 
}
Run Code Online (Sandbox Code Playgroud)

对于 的类型而言,它们都是可接受的工厂方法Vehicle,但对于 的颜色而言,它们不是面向工厂的方法Vehicle

要获得一个可以同时处理Type和Color的工厂方法,工厂方法

    public Vehicle newVehicle(String type, String color) { ... } 
Run Code Online (Sandbox Code Playgroud)

可能会被添加。请注意,有时某些组合没有任何意义,因此可能不值得将所有工厂方法打包到单个工厂方法中。

工厂对象中的任何方法都不是真正的工厂方法,除非它有可能返回多个接口的基本类型。同样,如果您必须指定如何在方法之外构建对象,那么它也不是工厂方法。

如果您需要将如何构建的控制权传递Vehicle给“这将是一个工厂”方法的客户端,同时提供一些安全性,让他们以合理的方式使用它,那么您需要Builder pattern. Builder Pattern在下面的客户端代码中可以看到a 有何不同的示例

 VehicleBuilder builder = new VehicleBuilder();
 builder.addDoor("driver");
 builder.addDoor("passenger");
 builder.paintVehicle("red");
 Vehicle vehicle = builder.getVehicle();
Run Code Online (Sandbox Code Playgroud)