首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >工厂设计模式和对OCP (开闭原则)的违反

工厂设计模式和对OCP (开闭原则)的违反
EN

Stack Overflow用户
提问于 2020-04-12 15:25:28
回答 2查看 321关注 0票数 5

this tutorial的工厂显然违反了OCP。每次将形状添加到系统中时,我们都需要在工厂中添加它以支持它。我正在考虑另一个实现,我想知道它是否有任何缺点。

代码语言:javascript
复制
public class ShapeFactory {

   //use getShape method to get object of type shape
   public Shape getShape(Class<? extends Shape> shapeType){
      return shapeType.newInstance();
   }
}

这个实现看起来并不违反OCP,也不复杂。有什么原因让我找不到任何提到它的工厂设计模式教程吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-04-12 16:08:26

我认为@hfontanez对"Does the Factory Pattern violate the Open/Closed Principle?"涵盖的问题的答案。如果您正在添加新的Shape子类,您还必须以某种方式添加一种方法来创建它们的实例。假设您不能修改原始ShapeFactory,因为它是第三方库的一部分,但您可以子类化或修饰原始工厂以添加对新形状的支持。扩展示例将如下所示:

代码语言:javascript
复制
public class AdvancedShapeFactory {
  private final ShapeFactory factory = new ShapeFactory();

  public Shape getShape(String shapeType) {
    if (shapeType.equalsIgnoreCase("PENTAGON")) {
      return new Pentagon();
    } else {
      return factory.getShape(shapeType);
    }
  }    
}

如果最初虚构的" shapes“库的设计者希望通过形状类型轻松创建新的形状,他们可以实现一个注册表:

代码语言:javascript
复制
public class ShapeRegistry {
  private static final Map<String, Class<Shape>> shapeTypes = new HashMap<>();

  public void registerShape(String shapeType, Class<Shape> shapeClass) {
    shapeTypes.put(shapeType, shapeClass);
  }

  public Shape getShape(String shapeType) throws InstantiationException, IllegalAccessException {
    if (shapeTypes.containsKey(shapeType)) {
      return shapeTypes.get(shapeType).newInstance();
    }
    return null;
  }
}

dependency injectionGuice是一个很好的例子,值得一读。

票数 2
EN

Stack Overflow用户

发布于 2020-04-12 15:40:59

这种方法有一些缺点。

首先,当传递给getShape的类需要构造函数参数时,.newInstance将失败。例如:

代码语言:javascript
复制
public class Circle {
   public Circle(int diameter) {
      //something
   }
}

您可以通过使用getConstructor并找出要传递的参数来进入反射,但这很复杂且容易出错。而且在编译时会失去类型安全性。工厂类如何知道要传递给diameter的值?

工厂设计模式的一个优点是,调用者在调用时不必知道使用了什么实现类。下面是一个例子:

代码语言:javascript
复制
public class ShapeFactory {
   public Shape getCircle(int diameter){
      return new Circle(int diameter);
   }
}

无论何时调用此方法,调用方都不需要依赖Circle类:

代码语言:javascript
复制
Shape s = ShapeFactory().getCircle(10);
s.draw();

这样,只有ShapeFactory依赖于Circle。因此,当您更改或替换Circle类时,只需更改ShapeFactory

为了使shape程序与OCP兼容,我们可以用依赖注入框架替换ShapeFactory。下面的代码是伪代码,它展示了这是如何工作的

代码语言:javascript
复制
// define the classes
class Circle {}
class Square {}

// for every class, provide a factory method. These do not have to exist inside a factory class.
public Circle createCircle() {
    return new Circle(10)
}

public Circle createSquare() {
    return new Square(42, 5)
}


public class Painter {
    //when a class requires an instance of the Circle class, the dependency injection framework will find `createCircle`, call it and add the result as an argument here.
    public Painter(Circle circle) {
       circle.draw();
    }
}


//when you need a painter object, we don't create it yourself but let the dependency framework do the heavy lifting
Painter p = dependencyframework.getInstanceOf(Painter.class)

有很多Java依赖注入框架,但它们的工作原理都是这样的。

这些框架做的和你建议的完全一样(像newInstancegetConstructor,但更多),它们只是隐藏了所有反射的复杂性。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61168108

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档