好吧,这完全取决于您将使用的语言来支持设计理念。我将用 Java 描述这个想法,让我们开始吧。
您有以下内容:
AbstractFacotry instance1 = new ConcreteFacotry1();
AbstractFacotry instance2 = new ConcreteFacotry2();
您想避免放置ConcretFactory#。这就是为什么您将使用一个工厂类,该类负责根据参数(在您的情况下,您提到的数据库记录)为您提供正确的ConcretFactory#实例。我会尽量简明扼要地解释,希望我不会在这个过程中失去任何人。
为了示例的目的,我将从创建抽象类AbstractFactory和从它扩展的具体类开始。
public abstract class AbstractFactory {}
当然你的会更详细,我只需要实例化它来运行几个测试。现在让我们来扩展它的类:
public class ConcreteFactory1 extends AbstractFactory {}
我不会粘贴其他的代码,它们都是一样的。以下是我创建的类:ConcreteFactory1、ConcreteFactory2、ConcreteFactory3、ConcreteFactory4。
接下来是负责根据您的数据库参数为您提供 AbstractFactory 的具体实例的类。此实现假定不会有超过 15 个左右的数据库参数。并且还可以将所述数据库参数转换为字符串。
public class FactoryInstantiator {
public AbstractFactory optionOne(){
return new ConcreteFactory1();
}
public AbstractFactory optionTwo(){
return new ConcreteFactory2();
}
public AbstractFactory optionThree(){
return new ConcreteFactory3();
}
public AbstractFactory optionFour(){
return new ConcreteFactory4();
}
}
显然 name option#是您的数据库参数的字符串翻译。
最后一件事是创建一个类,该类负责根据数据库参数调用正确的方法。这是果汁所在的地方,也是你避免使用 if-else 和 switch 的地方。这是您将从客户端调用的课程。
public class FactoryHandler {
public AbstractFactory getInstance(String databaseParameter) {
try {
return getConcreteInstance(FactoryInstantiator.class, databaseParameter);
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException |
InvocationTargetException | NoSuchMethodException ex) {
Logger.getLogger(FactoryHandler.class.getName()).log(Level.SEVERE, null, ex);
}
throw new RuntimeException("Could not determine concrete instance based on data base parameter");
}
private AbstractFactory getConcreteInstance(Class<FactoryInstantiator> factoryInstantiator, String databaseParameter)
throws InstantiationException, IllegalAccessException, IllegalArgumentException,
InvocationTargetException, NoSuchMethodException {
Class[] methodParameterTypes=null;
Object instance = factoryInstantiator.newInstance();
Method method = factoryInstantiator.getDeclaredMethod(databaseParameter, methodParameterTypes);
return (AbstractFactory) method.invoke(instance);
}
}
具体来说,您将调用getInstance(...)方法来获取您的具体实例。此方法负责捕获调用getConcreteInstance(..)可能产生的任何异常。这种分离是为了可读性和清晰性。
真正的处理是在getConcreteInstance(..)中负责根据 dbParameter 在FactoryInstantiator中调用适当的方法。
让我们在主类中使用它,如下所示:
public class Main {
public static void main(String[] args) {
ArrayList<AbstractFactory> factories = new ArrayList<>();
ArrayList<String> dbParameters = getDBparameters();
FactoryHandler factoryHandler = new FactoryHandler();
for(String dbParameter:dbParameters)
factories.add( factoryHandler.getInstance(dbParameter) );
for(AbstractFactory factory : factories)
System.out.println(factory.getClass());
}
private static ArrayList<String> getDBparameters(){
ArrayList<String> dbparameters = new ArrayList<>();
dbparameters.add("optionOne");
dbparameters.add("optionTwo");
dbparameters.add("optionThree");
dbparameters.add("optionFour");
return dbparameters;
}
}
这是打印输出:
class ConcreteFactory1
class ConcreteFactory2
class ConcreteFactory3
class ConcreteFactory4
你有它。希望能帮助到你。