如何在 Java 中创建自注册工厂?



工厂模式违反了OCP原则,因为它使用if()语句,这意味着如果添加任何类,则必须更改工厂类,这违反了SOLID原则。自注册类应该根据以下资源解决此问题:http://www.jkfill.com/2010/12/29/self-registering-factories-in-c-sharp/。问题是我不懂C#。有人可以在Java中举一个例子吗?提前谢谢。

public class ShapeFactory {
//The purpose of self registering classes is to avoid if's
public Shape getShape(String shapeType){
if(shapeType == null){ //Get rid of this
return null;
}     
if(shapeType.equalsIgnoreCase("CIRCLE")){
return new Circle();
} else if(shapeType.equalsIgnoreCase("RECTANGLE")){
return new Rectangle();
} else if(shapeType.equalsIgnoreCase("SQUARE")){
return new Square();
}
return null;
}
}

这种自我注册的东西是个坏主意。 最终,将很难知道哪些工厂实际注册,它们的名称是什么,以及因此支持哪些名称字符串。

保持简单明了更好,也更容易。 通常,它会像这样:

  • ShapeFactory应该有一个将形状类型字符串映射到相应工厂的Map<String, Supplier<Shape>>;和
  • ShapeFactory,或它的构建器,应该有一个addShapeType(String,Supplier<Shape>),用于在创建ShapeFactory实例时注册所有类型。

在我的 github 项目中的完整演示。

开-闭原则指出,软件实体必须扩展开放,但对修改关闭。让我们使用 OP 的示例:

public class ShapeFactory {
//The purpose of self registering classes is to avoid if's
public Shape getShape(String shapeType){
if(shapeType == null){ //Get rid of this
return null;
}     
if(shapeType.equalsIgnoreCase("CIRCLE")){
return new Circle();
} else if(shapeType.equalsIgnoreCase("RECTANGLE")){
return new Rectangle();
} else if(shapeType.equalsIgnoreCase("SQUARE")){
return new Square();
}
return null;
}
}

假设我需要添加三个新形状:TrianglePentagonHexagon。OCP 告诉我,我不应该修改现有的ShapeFactory来支持这些新形状,而是应该扩展现有类来支持它们。那么,我该怎么做呢?我可以从字面上扩展ShapeFactory并将三个新形状添加到这个子拉子中。那将是一个可怕的错误。因此,我将创建一个AbstractShapeFactoryShapeFactory以及我的新工厂类将扩展。也就是说,我更喜欢使用接口而不是抽象类。因此,我将创建一个形状工厂接口,然后我的混凝土工厂将实现该接口。

在不过多研究利斯科夫替代原则的情况下,您必须确保在此过程中不会违反这一原则。简而言之,您最终会得到这样的东西:

interface ShapesFactory {
// Shape should also be an interface
public Shape getShape(String name);
}
<小时 />
public class BasicShapesFactory implements ShapesFactory {
@Override
public Shape getShape(String name){
String errorMsg = name + " is not a legal name for a Shape.";
if(name == null){ //Get rid of this
throw new IllegalShapeException(errorMsg);
}
switch(name.toUpperCase()) {
case "CIRCLE":
return new Circle();
case "RECTANGLE":
return new Rectangle();
case "SQUARE":
return new Square();
default:
throw new IllegalShapeException(errorMsg);
}
}
}
<小时 />
public class AdvancedShapesFactory implements ShapesFactory {
@Override
public Shape getShape(String name){
String errorMsg = name + " is not a legal name for a Shape.";
// This null check could be extracted to a default function in the interface
if(name == null){ //Get rid of this
throw new IllegalShapeException(errorMsg);
}
switch(name.toUpperCase()) {
case "TRIANGLE":
return new Triangle();
case "PENTAGON":
return new Pentagon();
case "HEXAGON":
return new Hexagon();
default:
throw new IllegalShapeException(errorMsg);
}
}
}

现在您已经有了此结构,您可以创建抽象工厂,该工厂将为基本形状或高级形状提供工厂。

我认为添加if语句违反了 OCP 是一种误解。代码将被修改。添加类是对现有代码的修改。真正的问题是修改发生的位置和原因。我不会说使用像豆厂这样的东西是更好的解决方案,但概念是一样的。使用 OCP,您所做的只是通过扩展而不是修改它来保护"ShapeFactory"是什么。

最新更新