3

I have a project where I work with generated classes for some web interfaces. Some of these classes are (almost) identical and most of the functionality I need them for only use the identical parts. Currently that functionality is implemented for each class separately. I want to refactor it in a way that I only have to implement the functionality once, independent of the used classes.

package a;
public class Domain{
  //some attributes
  public String getName(){//impl};
  public String getType(){//impl};
  public Boolean getDnsSec(){//impl};
  //some setters
}
package b;
public class Domain{
  //some attributes
  public String getName(){//impl};
  public String getType(){//impl};
  public Boolean getIsSecured(){//impl};
  public String getLastEditor(){//impl};
  //some setters
}
package c;
public class Domain{
  //some attributes
  public String getName(){//impl};
  public String getType(){//impl};
  public Boolean getDnsSec(){//impl};
  //some setters
}

My current idea is to use some kind of adapter pattern but I'm not sure if it's the right approach and if I'm doing it the correct way. The implementation would look something like this:

public abstract class DomainAdapter <Domain>{
  private Domain domain;
  public DomainAdapter(Domain domain){
    this.domain = domain;
  }
  public abstract String getName();
  public abstract String getType();
  public abstract Boolean getDnsSec();
  public Domain getDomain(){
    return this.domain;
  }
}
public DomainAAdapter extends DomainAdapter<a.Domain>{
  public DomainGkAdapter(a.Domain domain) {
    super(domain);
  }
  @Override
  public String getName() {
    return getDomain().getName();
  }
  @Override
  public String getType(){
    return getDomain().getType();
  };
  @Override
  public Boolean getDnsSec(){
    return getDomain().getDnsSec();
  };
}

I'm wondering if this a good approach, if there is something better I could do or if it's maybe just wrong what I'm trying to do here. Thanks for the help and feedback in advance.

For clarification: I can not alter the Domain classes in package a, b, and c in any way. I think currently they are rebuilt from WSDL every time I build the project again and definitely need to be rebuilt if the corresponding WSDL gets updated. I do want a single point of access for these classes when I use them in my project though.

Instead of having three methods working with a.Domain, b.Domain or c.Domain as parameter, I want to have one function that works with a generalized domain parameter. Classic inheritance isn't possible since I cannot add a superclass that a.Domain, b.Domain and c.Domain inherit from.

Example:

//without adapter
public class DomainUser{
  public void useDomain(a.Domain domain){
    doSomething(domain.getName());
  }
  public void useDomain(b.Domain domain){
    doSomething(domain.getName());
  }
  public void useDomain(c.Domain domain){
    doSomething(domain.getName());
  }
}
//with adapter
public class DomainUser{
  public void useDomain(DomainAdapter domain){
    doSomething(domain.getName());
  }
}

To make things simpler you can assume that a.Domain, b.Domain and c.Domain are from different libraries I import and that I have no influence over.

15
  • can you not use inheritance? Commented Apr 24, 2019 at 11:59
  • Can you elaborate what problem this adapter approach should solve for you? Can you have the Domain classes inherit from a common interface? Commented Apr 24, 2019 at 12:06
  • 1
    The initial domain classes are generated from WSDL and cannot be altered. So simply adding a superclass or common interface doesn't work. Commented Apr 24, 2019 at 13:01
  • 1
    If you cannot generate your adapter-classes you gain nothing by generating the classes from WSDL instead of writing them by hand. Commented Apr 24, 2019 at 13:26
  • 1
    It's generated code. Why are you counting lines? Commented Apr 24, 2019 at 15:15

1 Answer 1

1

If your domain object are read-only you can convert them to single internal representation (you can automate conversion with tools like mapstruct).

If you need to mutate your domain objects while processing them you either wrap them in adapters (look into lombok, it have @Delegate that may help you) as you proposed or use strategy pattern like this:

<T> void setProperty(Strategy<T> s, T domain, String value) {
    s.setProperty(domain, value);
} 

where Strategy is:

interface Strategy<T> {
    void setProperty(T domain, String value);
}
class ADomainStrategy implements Strategy<a.Somain> {
    void setProperty(T domain, String value){
        domain.setProperty(value);
    }
}

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.