I am trying decouple a third party library's abstract class. I want to expose a new abstract class which will be exposed to the users rather than the library provided class.
I initially tried using an adapter but that stills add the import for the third party lib in the adapter class.
I added code below explaining my new approach.
// third party lib
abstract class ThirdParty<S> {
public abstract S doAction(S s);
}
// my goal here is to expose a different abstract class which is decoupled from third party lib
// exposed to other modules, rather than exposing the third party lib
abstract class ExposedAbstractClass<S> {
public abstract S doAction(S source);
// get hold of type using guava lib
private final TypeToken<S> typeToken = new TypeToken<S>(getClass()) { };
public Class<S> getSourceClass() { return (Class<S>) typeToken.getClass()
}
// internal class
class Builder<S> extends ThirdPartyLib<S> {
ExposedAbstractClass exposed;
public Builder(ExposedAbstractClass exposed) {
this.exposed = exposed;
}
@Override
public S doAction(S s) {
return (S) exposed.doAction(s);
}
}
//my approach breaks here when i try to invoke builder
class InvokeThirdParty {
public void invoke (ExposedAbstractClass exposed) {
Class type = exposed.getSourceClass();
Builder<type> builder = new Builder(exposed); //doesn't work since Class is runtime type, and T is compile time type
}
}
Any guidance in terms of which design pattern to follow here would be very helpful.
I agree with GuaravJ answer, you could isolate the third party dependency and use an Adaptor or Bridge pattern to invoke the third party library from there. I believe this would be an adequate decoupled solution.
However, it would seem your intent is to remove the import
, hence the dependency?
ThirdParty
class?Java is compatible with Reflection-oriented-programming. This lets you inspect and examine classes and invoke their methods dynamically at runtime. It would eliminate the dependency and the import
statement for the ThirdParty
class.
In general terms, with Reflection, you have to locate the class and inspect its methods. In this case I'm assuming knowledge of the doAction()
method from ThirdPartyClass
.
// import ThirdPartyLibrary statement somewhere here
// Instantiating object with concrete class that implements methods from ThirdParty. From your code now, it would be "Builder".
ThirdParty<S> thirdPartyObject = new ThirdPartyImp<S>();
// Invoking doAction method which returns an S object
S foo = thirdPartyObject.doAction();
// Inspect the class finding it using its path and instantiating an object
ThirdParty<S> thirdPartyObject = Class.forName("classpath.to.ThirdPartyImp").newInstance(); // Using a concrete class to instantiate.
// Finding the doAction method. This is assuming we have knowledge that a method with this name exists. Reflection could go as deep as not knowing the methods and having some control structure inspecting them.
Method doAction = thirdPartyObject.getClass().getDeclaredMethod("doAction", new Class<?>[0]);
// Do action is invoked and it returns an object S.
S foo = thirdPartyObject.invoke(thirdPartyObject);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With