我有一些类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) {
}
}
答案 0 :(得分:4)
多态性是一种可能性。如果Base类包含一个抽象的action()方法,你可以直接调用它,不需要任何if语句。
另一个是注册表。对于Base的每个子类,您可以注册到服务类的映射。在someMethod()中,在注册表中查找类,获取相应的服务类,然后调用它。
顺便说一句,详细程度不是instanceof语句的唯一问题。一旦创建了一个新的Base子类,用这些编写的代码就会中断。满足Open/Closed principle可能会导致代码不那么脆弱。
答案 1 :(得分:2)
一种可能的解决方案是使用Visitor
模式。您需要将FooService
和BarService
合并到一个具有重载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()
方法。