🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
### 动态工厂 前面例子中的**静态**`create()`方法强制所有创建操作都集中在一个位置,因此这是添加新类型的**Shape**时唯一必须更改代码的地方。这当然是一个合理的解决方案,因为它把创建对象的过程限制在一个框内。但是,如果你在添加新类时无需修改任何内容,那就太好了。 以下版本使用反射在首次需要时将**Shape**的构造器动态加载到工厂列表中: ```java // patterns/ShapeFactory2.java import java.util.*; import java.lang.reflect.*; import java.util.stream.*; import patterns.shapes.*; public class ShapeFactory2 implements FactoryMethod { Map<String, Constructor> factories = new HashMap<>(); static Constructor load(String id) { System.out.println("loading " + id); try { return Class.forName("patterns.shapes." + id) .getConstructor(); } catch(ClassNotFoundException | NoSuchMethodException e) { throw new BadShapeCreation(id); } } public Shape create(String id) { try { return (Shape)factories .computeIfAbsent(id, ShapeFactory2::load) .newInstance(); } catch(InstantiationException | IllegalAccessException | InvocationTargetException e) { throw new BadShapeCreation(id); } } public static void main(String[] args) { FactoryTest.test(new ShapeFactory2()); } } ``` 输出结果: ```java loading Circle Circle[0] draw Circle[0] erase loading Square Square[1] draw Square[1] erase loading Triangle Triangle[2] draw Triangle[2] erase Square[3] draw Square[3] erase Circle[4] draw Circle[4] erase Circle[5] draw Circle[5] erase Triangle[6] draw Triangle[6] erase ``` 和之前一样,`create()`方法基于你传递给它的**String**参数生成新的**Shape**s,但是在这里,它是通过在**HashMap**中查找作为键的**String**来实现的。 返回的值是一个构造器,该构造器用于通过调用`newInstance()`创建新的**Shape**对象。 然而,当你开始运行程序时,工厂的`map`为空。`create()`使用`map`的`computeIfAbsent()`方法来查找构造器(如果该构造器已存在于`map`中)。如果不存在则使用`load()`计算出该构造器,并将其插入到`map`中。 从输出中可以看到,每种特定类型的**Shape**都是在第一次请求时才加载的,然后只需要从`map`中检索它。