是否有更好的方法来处理对象(Product
)的实例化,这取决于另一种对象类型(Condition
)而不是使用if-else与instanceof
配对作为以下代码显示?
import java.util.ArrayList;
import java.util.List;
abstract class AbstractProduct {
private AbstractCondition condition;
public AbstractProduct(AbstractCondition condition) {
this.condition = condition;
}
public abstract void doSomething();
}
class ProductA extends AbstractProduct {
AbstractCondition condition;
public ProductA(AbstractCondition condition) {
super(condition);
}
@Override
public void doSomething() {
System.out.println("I'm Product A");
}
}
class ProductB extends AbstractProduct {
public ProductB(AbstractCondition condition) {
super(condition);
}
@Override
public void doSomething() {
System.out.println("I'm Product B");
}
}
class AbstractCondition { }
class ConditionA extends AbstractCondition { }
class ConditionB extends AbstractCondition { }
public class Try {
public static void main(String[] args) {
List<AbstractCondition> conditions = new ArrayList<AbstractCondition>();
List<AbstractProduct> products = new ArrayList<AbstractProduct>();
conditions.add(new ConditionA());
conditions.add(new ConditionB());
conditions.add(new ConditionB());
conditions.add(new ConditionA());
for (AbstractCondition c : conditions) {
tryDoSomething(c);
}
}
public static void tryDoSomething(AbstractCondition condition) {
AbstractProduct product = null;
if (condition instanceof ConditionA) {
product = new ProductA(condition);
} else if (condition instanceof ConditionB) {
product = new ProductB(condition);
}
product.doSomething();
}
}
差异与我的真实代码上面的代码是:我有 NO 直接控制AbstractCondition
及其子类型(因为它们在库中) ),但AbstractProduct
的具体子类型的创建取决于具体条件。
我的目标是:尽量避免if-else
中的tryDoSomething()
代码异味。
我也想避免反思,因为它感觉像是在作弊,我认为这不是一个优雅,干净和可读的解决方案。
换句话说,我想用优秀的OOP原则(例如利用多态性)解决问题并解决一些设计模式(在这个特定情况下我显然不知道)。
答案 0 :(得分:3)
由于无法编辑原始对象,因此需要创建从条件类型到产品类型的静态地图:
private static HashMap< Class<? extends AbstractCondition>,
Class<? extends AbstractProduct>
> conditionToProduct;`
使用Condition,Product:
对进行静态初始化static {
conditionToProduct.put(ConditionA.class, ProductA.class);
...
}
并在运行时只查询地图:
Class<? extends AbstractProduct> productClass = conditionToProduct.get(condition.getClass());
productClass.newInstance();
答案 1 :(得分:2)
AbstractCondition
需要知道类型或如何构建产品。
因此,请将以下某个功能添加到AbstractCondition
Class<? extends AbstractProduct> getProductClass()
或
AbstractProduct createProduct()
答案 2 :(得分:0)
您应该创建一个Factory类来帮助您。
interface IFactoryProduct{
AbstractProduct getProduct(AbstractCondition condition) throws Exception;
}
这将是您的界面,只需要像这样实现它。
class FactoryProduct implements IFactoryProduct{
public AbstractProduct getProduct(AbstractCondition condition) throws Exception{
return (AbstractProduct)getClass().getMethod("getProduct", condition.getClass()).invoke(this, condition);
}
public ProductA getProduct(ConditionA condition){
return new ProductA();
}
public ProductB getProduct(ConditionB condition){
return new ProductB();
}
}
使用反射以正确的方法重定向将起到作用。如果你愿意,这可以升级为子类。
编辑:
一些例子:
List<AbstractCondition> list = new ArrayList<AbstractCondition>();
list.add(new ConditionA());
list.add(new ConditionB());
for(AbstractCondition c : list){
try {
System.out.println(f.getProduct(c));
} catch (Exception ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
}
labo.ProductA@c17164
labo.ProductB@1fb8ee3
更复杂的反射版本,允许接收子类:
public AbstractProduct getProduct(AbstractCondition condition) throws Exception{
Method m = getMethodFor(condition.getClass());
if(m == null )
throw new Exception("No method for this condition " + condition.getClass().getSimpleName());
else
return (AbstractProduct) m.invoke(this, condition);
}
private Method getMethodFor(Class<? extends AbstractCondition> clazz ) throws Exception{
try {
return getClass().getMethod("getProduct", clazz);
} catch (NoSuchMethodException ex) {
if(clazz.getSuperclass() != AbstractCondition.class){
return getMethodFor((Class<? extends AbstractCondition>)clazz.getSuperclass());
}
return null;
}
}
这允许我发送ConditionC extending ConditionB
以构建具有ConditionB
的相同产品。对复杂遗产感兴趣。