如何根据对象instanceof选择要执行的操作?

时间:2013-04-01 00:27:23

标签: java oop design-patterns

我有一些类Base的实现,所有对象都收集在List<Base>中。

如何根据action这些对象调用特定的instanceof,而不必使用详细的instanceof检查?我如何根据这些对象的实例选择要执行的servicemethod,但不必关心执行该操作的对象。应该以某种方式自动选择正确的服务方法,而无需使用typecasing或instanceof检查。

class Base;
class Foo extends Base;
class Bar extends Base;

class Service {
    List<Base> bases;

    public void someMethod() {
        for (Base base : bases) {
            //perform some instanceof dependend action.
            //these actions cannot be inside of any Base class as it makes use of other objects too.
            if (base instanceof Foo) {
                fooService.action((Foo) base);
            }
            if (base instanceof Bar) {
                barService.action((Bar) base);
            }
        }
    }
}


//custom service methods
class FooService {
    void action(Foo foo) {
    }
}

class BarService {
    void action(Bar bar) {
    }
}

3 个答案:

答案 0 :(得分:4)

多态性是一种可能性。如果Base类包含一个抽象的action()方法,你可以直接调用它,不需要任何if语句。

另一个是注册表。对于Base的每个子类,您可以注册到服务类的映射。在someMethod()中,在注册表中查找类,获取相应的服务类,然后调用它。

顺便说一句,详细程度不是instanceof语句的唯一问题。一旦创建了一个新的Base子类,用这些编写的代码就会中断。满足Open/Closed principle可能会导致代码不那么脆弱。

答案 1 :(得分:2)

一种可能的解决方案是使用Visitor模式。您需要将FooServiceBarService合并到一个具有重载action()方法的类中。然后,您需要为每个accept()Foo类添加Bar方法,然后可以调用相应的action()方法。有关详细信息,请参阅http://en.wikipedia.org/wiki/Visitor_pattern

可能有其他更合适的design patterns可以解决这个问题。我建议你研究它们。

答案 2 :(得分:0)

我最接近解决这个问题的是:

class Base{};
class Foo extends Base{};
class Boo extends Base{};

附加的BaseService接口,因此每个服务类都使用相同的方法:

public interface BaseService<T extends Base> {

void action(T base);

}

BooService:

public class BooService implements BaseService<Boo> {

public void action(Boo boo){
    System.out.println("Action performed by BooService");
    }
}

FooService接口:

public class FooService implements BaseService<Foo> {

public void action(Foo foo){
    System.out.println("Action performed by FooService");
    }
}

附加的ServiceSupplier类,它将根据传递的对象调用适当的服务:

public class ServiceSupplier {

private Map<Class<? extends Base>, BaseService> services;

public ServiceSupplier(){
    initializeServiceMap();
}

public BaseService getServiceOfType(Class<? extends Base> clazz){
    return services.get(clazz);
}

private void initializeServiceMap() {
    services = new HashMap<>();
    services.put(Foo.class, new FooService());
    services.put(Boo.class, new BooService());
    }
}

您的服务类:

public class Service {
List<Base> bases;
ServiceSupplier serviceSupplier;

public Service(){
    serviceSupplier = new ServiceSupplier();

    bases = new ArrayList<>(Arrays.asList(new Foo(), new Boo()));
}

public void someMethod() {
    bases.forEach(base -> serviceSupplier.getServiceOfType(base.getClass()).action(base));
    }
}

似乎只是为了删除一些“if”语句,但只需要提供更多服务就可以将它们添加到initializeServiceMap()方法。