Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何根据对象实例选择要执行的操作?_Java_Oop_Design Patterns - Fatal编程技术网

Java 如何根据对象实例选择要执行的操作?

Java 如何根据对象实例选择要执行的操作?,java,oop,design-patterns,Java,Oop,Design Patterns,我有一些类Base的实现,所有对象都收集在一个列表中 如何基于这些对象的instanceof调用特定操作,而不必使用详细的instanceof检查?如何根据这些对象的实例选择要执行的servicemethod,而不必关心在哪个对象上执行操作。应该以某种方式自动选择正确的服务方法,而无需打字或即时检查 class Base; class Foo extends Base; class Bar extends Base; class Service { List<Base> b

我有一些类Base的实现,所有对象都收集在一个列表中

如何基于这些对象的instanceof调用特定操作,而不必使用详细的instanceof检查?如何根据这些对象的实例选择要执行的servicemethod,而不必关心在哪个对象上执行操作。应该以某种方式自动选择正确的服务方法,而无需打字或即时检查

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) {
    }
}

一种可能的解决方案是使用访问者模式。您需要将FooService和BarService组合成一个具有两个重载操作方法的类。然后,您需要向每个Foo和Bar类添加一个accept方法,然后这些类可以调用适当的操作方法。有关更多详细信息,请参阅


可能还有其他更合适的方法可以解决这个问题。我建议你研究一下它们。

一个可能的解决方案是使用访问者模式。您需要将FooService和BarService组合成一个具有两个重载操作方法的类。然后,您需要向每个Foo和Bar类添加一个accept方法,然后这些类可以调用适当的操作方法。有关更多详细信息,请参阅


可能还有其他更合适的方法可以解决这个问题。我建议你研究一下。多态性是一种可能性。如果基类包含抽象操作方法,则可以直接调用它,而无需任何If语句

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


顺便说一下,instanceof语句的唯一问题不是冗长。用这些代码编写的代码可能会在创建新的Base子类后立即中断。满足以下条件可以减少代码的脆弱性。

多态性是一种可能性。如果基类包含抽象操作方法,则可以直接调用它,而无需任何If语句

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


顺便说一下,instanceof语句的唯一问题不是冗长。用这些代码编写的代码可能会在创建新的Base子类后立即中断。满足以下条件可以减少代码的脆弱性。

我解决此问题的最接近方法是:

class Base{};
class Foo extends Base{};
class Boo extends Base{};
附加的BaseService接口,以便每个服务类使用相同的方法:

public interface BaseService<T extends Base> {

void action(T base);

}
服务:

public class BooService implements BaseService<Boo> {

public void action(Boo boo){
    System.out.println("Action performed by BooService");
    }
}
public class FooService implements BaseService<Foo> {

public void action(Foo foo){
    System.out.println("Action performed by FooService");
    }
}
餐饮服务:

public class BooService implements BaseService<Boo> {

public void action(Boo boo){
    System.out.println("Action performed by BooService");
    }
}
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方法中。

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

class Base{};
class Foo extends Base{};
class Boo extends Base{};
附加的BaseService接口,以便每个服务类使用相同的方法:

public interface BaseService<T extends Base> {

void action(T base);

}
服务:

public class BooService implements BaseService<Boo> {

public void action(Boo boo){
    System.out.println("Action performed by BooService");
    }
}
public class FooService implements BaseService<Foo> {

public void action(Foo foo){
    System.out.println("Action performed by FooService");
    }
}
餐饮服务:

public class BooService implements BaseService<Boo> {

public void action(Boo boo){
    System.out.println("Action performed by BooService");
    }
}
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方法中。

这有一种反模式的味道。策略模式在这里可以更好地工作,而不使用脆弱的实例of吗?或者使用某种工厂来加载服务方法。好吧,对于策略,我首先必须知道我在处理哪个Base实例,对吗?因为我最终会得到一个FooStrategy和一个BarStrategy,如果我想在所有Foo实例上调用FooStrategy,我必须首先执行instanceof check…您的注释//这些操作不能在任何基类内,因为它也使用其他对象。不清楚。动作使用其他对象的事实并不意味着它不能在子类中。如果多态性不能处理你的情况,那么我们或者至少我不理解你的情况,需要更多的解释。你能更好地解释为什么不能使用多态性吗?让我们把Foo,Bar看作域对象。要执行的操作是删除操作。根据基本对象的实例,在删除时应执行不同的操作,例如使用不同对象进行级联清理,删除域对象已知且不应知道的不同列表中的对象。因此,我不能/不想将这些代码移动到域对象中,因此不能使用多态性。这有一种反模式的味道。策略模式在这里可以更好地工作,而不使用脆弱的实例of吗?或者使用某种工厂来加载服务方法。好吧,对于策略,我首先必须知道我在处理哪个Base实例,对吗?因为我最终会得到一个美食策略和一个酒吧

策略,如果我想在所有Foo实例上调用FooStrategy,我必须首先执行instanceof check…您的注释//这些操作不能在任何基类内,因为它也使用其他对象。不清楚。动作使用其他对象的事实并不意味着它不能在子类中。如果多态性不能处理你的情况,那么我们或者至少我不理解你的情况,需要更多的解释。你能更好地解释为什么不能使用多态性吗?让我们把Foo,Bar看作域对象。要执行的操作是删除操作。根据基本对象的实例,在删除时应执行不同的操作,例如使用不同对象进行级联清理,删除域对象已知且不应知道的不同列表中的对象。因此,我不能/不想将这些代码移动到域对象中,因此不能使用多态性。好吧,这很好,但是:如果我有5种特定于实例的方法呢?这意味着我必须编写5个访问者,并且为每个新的依赖实例的行为编写一个新访问者。@member By instance-specific-methods,您是说每个服务类中有5个方法吗?如果是这样,那么您几乎肯定需要使用不同的设计模式。我相信只要稍加研究,你就能找到适合你需要的东西。是的,比如说我有一些添加、删除、修改和更新方法。它们中的每一个都应该依赖于实例,这意味着Foo的add应该不同于Bar的add。无论如何,我想把所有的基本对象都保存在一个列表中,然后在列表上迭代执行addbase。。。你有更好的设计建议吗。因为,正如我在这里所问的,到目前为止,我自己还没有想出一个更好的方法…@membersound我建议你从我在答案中给出的设计模式链接开始,或者看看其他人的建议。好的,那很好,但是:如果我有5种特定于实例的方法呢?这意味着我必须编写5个访问者,并且为每个新的依赖实例的行为编写一个新访问者。@member By instance-specific-methods,您是说每个服务类中有5个方法吗?如果是这样,那么您几乎肯定需要使用不同的设计模式。我相信只要稍加研究,你就能找到适合你需要的东西。是的,比如说我有一些添加、删除、修改和更新方法。它们中的每一个都应该依赖于实例,这意味着Foo的add应该不同于Bar的add。无论如何,我想把所有的基本对象都保存在一个列表中,然后在列表上迭代执行addbase。。。你有更好的设计建议吗。因为,正如我在这里所问的,到目前为止,我自己还没有想出一个更好的…@membersound我建议你从我在答案中给出的设计模式链接开始,或者看看其他人的建议。是的,但是如上所述,我不能在我的基类中进行操作,因为它更多的是一种服务方法,同时也使用其他对象。否则多态性很容易实现,但我正在寻找一种方法来处理这个问题,而不必将逻辑放在基本实现中。您是否考虑过第二种可能性——注册表?是的,这可能是我唯一可以选择的方法,尽管我对注册表查找感到不太舒服。从设计的角度来看,它也感觉不对劲。那么,最好是更改基本对象并引入getService方法,这样每个实现都必须提供自己的服务。注册也可以在不修改基类的情况下完成。例如,您可以拥有从数据类型到用户界面元素的注册表,而无需将数据层耦合到表示层。是的,但如上所述,我不能在基类中拥有该操作,因为它更像是一种服务方法,还可以使用其他对象。否则多态性很容易实现,但我正在寻找一种方法来处理这个问题,而不必将逻辑放在基本实现中。您是否考虑过第二种可能性——注册表?是的,这可能是我唯一可以选择的方法,尽管我对注册表查找感到不太舒服。从设计的角度来看,它也感觉不对劲。那么,最好是更改基本对象并引入getService方法,这样每个实现都必须提供自己的服务。注册也可以在不修改基类的情况下完成。例如,您可以拥有从数据类型到用户界面元素的注册表,而无需将数据层耦合到表示层。