工厂模式动态方法
我试图了解工厂模式。如果有很多实现,那么我的工厂模式将有很多if else或switch情况。 而且每次我介绍一个新的实现时,我都应该更改我的工厂代码
如下面的例子中假如狗狗鸭子正在实施宠物界面,如果许多动物实施宠物界面我的工厂如果代码或转换案件还有很多其他的话。 有没有办法通过带来更多动态方法来解决这个问题?
package com.javapapers.sample.designpattern.factorymethod; //Factory method pattern implementation that instantiates objects based on logic public class PetFactory { public Pet getPet(String petType) { Pet pet = null; // based on logic factory instantiates an object if ("bark".equals(petType)) pet = new Dog(); else if ("quack".equals(petType)) pet = new Duck(); return pet; }
如果动物长大
if ("bark".equals(petType)) pet = new Dog(); else if ("quack".equals(petType)) pet = new Duck(); else if ("mno".equals(petType)) pet = new MNO(); else if ("jkl".equals(petType)) pet = new JKL(); else if ("ghi".equals(petType)) pet = new GHI(); else if ("def".equals(petType)) pet = new DEF(); ...... else if ("abc".equals(petType)) pet = new ABC(); return pet
我认为有一种动态的方法:
- 在你的工厂,你需要一个
Map
> Map
> - 在扩展Pet的每个类的静态构造函数中,使用这样的map注册它。
- 比创建一个类只是
map.get(pet).newInstance
(当然你必须检查空值)
工厂模式背后的想法是让您动态实例化在设计时不一定知道的类型的对象。
拥有一个巨大的if
块会击败这个目的。
实现此模式的有效方法是为每种类型都有一个工厂,它实现了一个基础工厂接口,并且能够实例化该类型的新对象(顺便说一下,在Java中,内置Class
是一个这种工厂的例子)。
然后你注册一个名称/ ids /等地图。 在运行时对这些单个工厂的实例。 当需要实例化其中一种类型时,您可以按名称在地图中查找工厂,并使用它来实例化该类型的新对象。
你如何在地图上注册个别工厂完全在空中。 您可以明确注册一些,可以扫描配置文件等。
基本上,您希望使用在运行时动态创建的映射替换if
块。
您甚至不需要单独使用预先注册的“地图” – 有时可能适合弄清楚如何动态创建具有给定名称的对象,或两者的组合(例如, Class.forName()
搜索类路径,如果它找不到已加载的类)。 关键是将名称转换为类类型可以在没有基本工厂实际知道类类型的情况下进行。
值得注意的是,Javareflection已经通过Class.forName()
和/或Class.newInstance()
提供了非常可行的工厂实现,因此如果有意义,请考虑使用它而不是重新发明轮子。
用reflection
public Pet getPet(String petType) { Pet _pet = (Pet)Class.forName(petType).newInstance(); return _pet; }
你需要将你的论点从’bark’,’quack’改为’Dog’和’Duck’等
因为我有类似的问题,所以我一直在摸不着头脑,最后我找到了一个基于Reflections Library的解决方案(关注最后的S in Reflections!)
例如,如果您的所有宠物子类都具有可用于区分它们的属性,则它可以应用于您的问题
public String petType;
您工厂的方法可能如下:
public static Pet getPet(String _petType) { String packageName = "your.package.with.pet.classes"; Reflections reflections = new Reflections(packageName); Set> allPets = reflections .getSubTypesOf(Pet.class); Iterator> it = allPets.iterator(); while (it.hasNext()) { try { Pet pet = it.next().newInstance(); if (pet.petType.equals(_petType)) return pet; } catch (InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } } System.out.println("Pet " + _petType + " not yet implemented in package " + packageName); return null; }
如果定义了新的宠物,这种方法将不受影响。
优点:
-
它不需要对Pet子类进行进一步修改,也不需要对Factory维护的Map结构进行任何类型的初始化/注册
-
它比基于Java Reflection API的解决方案更通用,因为您可以在某些属性而不是类名上区分Pet子类
缺点:
- 它创建所有Pet子类的本地实例以找到合适的子类。 在这方面,我相信这种方法可以改进。