简体   繁体   中英

Creating an enclosing class for two different objects in java

I'm having an issue that I can't find the right way to resolve by myself.

Basically I have two objects Object1 & Object2 where both of these have two properties of the same type:

public class Object1 {

    ...
    private String name;
    private String description;
    ...

    Object1 () {

    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }
}

public class Object2 {

    ...
    private String name;
    private String description;
    ...

    Object2 () {

    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }
}

Now obviously I made them properties as strings here in the example but in reality they're other types.

NOTE: Object1 and Object2 are actually generated classes from XML models that I need for SOAP servces. So I can't modify them.

In some point in my code I have to access say the 'name' property of either Object1 or Object2 depending on different factors. This point is an event handler so in a certain moment of time it catches an event called with Object1 and other times with Object2.

My guess was to make a single class that would enclose both these types and expose one single "name" property and one single "description" property.

What would a standard way of doing this be?

There basically are two ways to do this:

  1. Use a common interface that expose the getters and setters. Then let both classes implement that interface and let the handler use it.

  2. If possible (both objects don't already extend other superclasses) you could use an abstract superclass and put the properties as well as the getters and setters there. The handler then uses that superclass.

Note that both approaches can be combined, ie use an interface for the handler and use an abstract superclass that implements that interface as an adapter class, ie you could extend that adapter when possible or just implement the interface when extending the adapter is not possible.

Example:

interface Common { 
  String getName();
}

abstract class CommonAdapter implements Common {
   String name;

   String getName() {
     return name;
   }

   //setter as well
}

//just extend the adapter and enjoy
class Object1 extends CommonAdapter {
  //specific code for Object1
}

//extending not possible, so implement the interface directly
class Object2 extends SomeOtherClass implements Common {
  String name;

  String getName() {
    return name;
  }
}

class Handler {
  void handle( Common c ) {
    c.getName();
    ...
  }
}

Update :

If the classes are generated, you could create those objects as wrappers and delegate all calls to the actual class, eg

class Object1CommonWrapper implements Common {
  Object1 delegate;

  String getName() {
    return delegate.getName();
  }
}

制作一个抽象类,让两个类都从中扩展

  1. Use interface or abstract class
 public interface CommonObject { //gettter and setter } public Class Object1 implements CommonObject { ... } public Class Object2 implements CommonObject { ... } public Class MainClass { public void someMethod() { if(someCondition) { CommonObject obj1 = new Object1(); //use obj1 } else { CommonObject obj2 = new Object1(); //use obj2 } } } 
  1. Use factory pattern

it depends a bit on the behaviour of said methods. So if:

  • Both Object1/ Object2 have the absolut identical code for those methods i would go with inheritance, have a superclass that defines those fields/ methods and the two objects extend it.
  • Both Object1/ object2 must have the same method signature but have to handle the internal logic in different ways i would go with a interface defining the method signature that both Object1/2 must implement.

You can define an interface that both Object1 and Object2 implement. The interface would include the methods that you need to call, but each class can implement them in its own way.

For example, it might look something like this:

public interface Describable {
    String getName();
    String getDescription();
}

public class Object1 implements Describable {
    ... implements the methods in some way
}

public class Object2 implements Describable {
    ... implements the methods in another way
}

With that, whatever code needs to deal with both of these types of objects can refer to them as Describable and take advantage of polymorphism. For example:

Describable eventObject = ...get the object...
eventObject.getName();
eventObject.getDescription();

Or even something like:

public void handle(Describable describable) {
    describable.getDescription();
    ... more stuff...
}

That code doesn't know (or care) what type of object is actually passed in to the method, only that it can interact with it as a Describable .

This is a common idiom in Java and OO design in general. The core libraries use it all over the place.

By the way, inheritance (ie, using a common base super class) is another option. Just be aware that the technique of implementation inheritance has some trade-offs and is often abused/misused. For example see this discussion .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM