I have some generated code (i.e. it cannot be changed) that looks something like this.
class Generated1 {
public String getA() {
return "1";
}
public void setB(String b) {
}
public void setC(String c) {
}
public void setD(String d) {
}
}
class Generated2 {
public String getA() {
return "2";
}
public void setB(String b) {
}
public void setC(String c) {
}
public void setD(String d) {
}
}
I am exploring these objects by reflection. None of them implement any common interface but there's many of them and I want to treat them as if they implement:
interface CommonInterface {
String getA();
void setB(String b);
void setC(String c);
void setD(String d);
}
It certainly should be possible. This is considered perfectly good code
class CommonInterface1 extends Generated1 implements CommonInterface {
// These are perfectly good classes.
}
class CommonInterface2 extends Generated2 implements CommonInterface {
// These are perfectly good classes.
}
I suppose what I'm looking for is something like:
private void doCommon(CommonInterface c) {
String a = c.getA();
c.setB(a);
c.setC(a);
c.setD(a);
}
private void test() {
// Simulate getting by reflection.
List<Object> objects = Arrays.asList(new Generated1(), new Generated2());
for (Object object : objects) {
// What is the simplest way to call `doCommon` with object here?
doCommon(object);
}
}
My question: How do I treat an object that doesn't implement an interface but actually has all the code to do so as if it does implement the interface.
I want to replace
private void doCommon(Generated1 c) {
String a = c.getA();
c.setB(a);
c.setC(a);
c.setD(a);
}
private void doCommon(Generated2 c) {
String a = c.getA();
c.setB(a);
c.setC(a);
c.setD(a);
}
...
with
private void doCommon(CommonInterface c) {
String a = c.getA();
c.setB(a);
c.setC(a);
c.setD(a);
}
I know I can use a Proxy like this but I'd really prefer to use something better.
private void test() {
// Simulate getting by reflection.
List<Object> objects = Arrays.asList(new Generated1(), new Generated2());
for (Object object : objects) {
// What is the simplest way to call `doCommon` with object here?
doCommon(adapt(object));
}
}
private CommonInterface adapt(Object o) {
return adapt(o, CommonInterface.class);
}
public static <T> T adapt(final Object adaptee,
final Class<T>... interfaceToImplement) {
return (T) Proxy.newProxyInstance(
adaptee.getClass().getClassLoader(),
interfaceToImplement,
// Call the equivalent method from the adaptee.
(proxy, method, args) -> adaptee.getClass()
.getMethod(method.getName(), method.getParameterTypes())
.invoke(adaptee, args));
}
If you're using reflection, you don't need the two CommonInterfaceX classes, you can use a proxy implementing CommonInterface:
public class Wrapper implements InvocationHandler {
private final Object delegate;
public static <T> T wrap(Object obj, Class<T> intf) {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
Object proxy = Proxy.newProxyInstance(cl, new Class<?>[] {intf},
new Wrapper(obj));
return intf.cast(proxy);
}
private Wrapper(Object delegate) {
this.delegate = delegate;
}
#Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Method dmethod = delegate.getClass().getMethod(
method.getName(), method.getParameterTypes());
return dmethod.invoke(delegate, args);
}
}
You can use this class as follows:
List<Object> objects = Arrays.asList(new Generated1(), new Generated2());
for (Object object : objects) {
CommonInterface proxy = Wrapper.wrap(object, CommonInterface.class);
doCommon(proxy);
}
UPDATE: note that the same Wrapper class works with any interface.
There's no way to achieve a static type relationship between Generated1 and Generated2.
Even if you created CommonInterface1 and CommonInterface2, you still wouldn't be able to statically use a Generated1 object as a CommonInterface1 because new Generated1() is not a CommonInterface1 (and will never become one)
By far the simplest solution is to change your code generation to add the CommonInterface to Generated1 and Generated2.
If that's absolutely impossible, the only other way to avoid this code duplication is to go for reflection.
You can do it manuallly by reflection.
public class Generated {
public String getA() {
return "A";
}
public String sayHello(String name) {
return "hello " + name;
}
}
public class Helper {
private static final String METHOD_NAME = "getA";
private static final String METHOD_WITH_PARAM_NAME = "sayHello";
public static void main(String[] args) throws Exception {
Generated generated = new Generated();
accessMethod(generated);
accessMethodWithParameter(generated);
}
private static void accessMethod(Generated g) throws Exception {
Method[] methods = g.getClass().getDeclaredMethods();
for(Method method : methods) {
if(isCommonMethod(method)) {
String result = (String) method.invoke(g);
System.out.println(METHOD_NAME + "() = " + result);
}
}
}
private static boolean isCommonMethod(Method m) {
return m.getName().equals(METHOD_NAME) && m.getReturnType().equals(String.class);
}
private static void accessMethodWithParameter(Generated g) throws Exception {
Method[] methods = g.getClass().getDeclaredMethods();
for(Method method : methods) {
if(isCommonMethodWithParameter(method)) {
String result = (String) method.invoke(g, "Max");
System.out.println(METHOD_WITH_PARAM_NAME + "(\"Max\") = " + result);
}
}
}
private static boolean isCommonMethodWithParameter(Method m) {
return m.getName().equals(METHOD_WITH_PARAM_NAME) &&
m.getReturnType().equals(String.class) &&
m.getParameterTypes().length == 1 &&
m.getParameterTypes()[0].equals(String.class);
}
}
Output is
getA() = A
sayHello("Max") = hello Max
If you want to replace as your comment. I think you can do it easily
First, you create interface CommonInterface
interface CommonInterface {
String getA();
void setB(String b);
void setC(String c);
void setD(String d);
}
After that, you create 2 class Generated1 and Generated2 inherited CommonInterface
class Generated1 implements CommonInterface {
#overide
public String getA() {
return "1";
}
#overide
public void setB(String b) {
}
#overide
public void setC(String c) {
}
#overide
public void setD(String d) {
}
}
class Generated2 implements CommonInterface {
#overide
public String getA() {
return "2";
}
#overide
public void setB(String b) {
}
#overide
public void setC(String c) {
}
#overide
public void setD(String d) {
}
}
Related
I'm messing around with lambdas and I'm trying to create a generic way to form a predicate for a class on a field. Here's some code to illustrate:
public class A {
private String b;
private String c;
public A(String b, String c) {
this.b = b;
this.c = c;
}
public String getB() {
return b;
}
public String getC() {
return c;
}
}
public class Main {
public static void main(String[] args) {
List<A> list = Arrays.asList(new A("aa","bb"),new A("aaC","bb"));
Test test = new Test();
test.setList(list);
test.createPred("aa");
}
}
public class Test {
private List<A> list;
public void setList(List<A> list) {
this.list = list;
}
public Predicate<A> createPred(String query) {
return new Predicate<A>() {
#Override
public boolean test(A t) {
return t.getB().equals(query);
}
};
}
public List<A> search(Predicate<A> a) {
return list.stream().filter(a).collect(Collectors.toList());
}
}
How can I write createPred so it can take a field? I want the method to be "field-generic" I suppose. I'm guessing using java reflection here is not a good idea.
You can make your method take a Function and a T as the query field.
public static void main(String[] args) {
List<A> list = Arrays.asList(new A("aa", "bb"), new A("aaC", "bb"));
Test test = new Test();
test.setList(list);
test.createPred("aa", A::getB);
}
public static class Test {
private List<A> list;
public void setList(List<A> list) {
this.list = list;
}
public <T> Predicate<A> createPred(T query, Function<A, T> f) {
return new Predicate<A>() {
#Override
public boolean test(A x) {
return f.apply(x).equals(query);
}
};
}
public List<A> search(Predicate<A> a) {
return list.stream().filter(a).collect(Collectors.toList());
}
}
Structure
-ClassA
|---|
|---ClassAImplA
|---ClassAImplB
-Main
Class A:
public interface ClassA {
public void execute();
}
Implementaion A:
public class ClassAImplA implements ClassA
{
private int a = 5;
public ClassAImplA (int a){setA(a);}
#Override
public void execute() {
System.out.println(a);
}
public int getA() {
return a;
}
public void setA(int a) {
this.a = a;
}
Implementaion B:
public class ClassAImplB implements ClassA
{
private boolean b = false;
public ClassAImplB (int a){setB(b);}
#Override
public void execute() {
System.out.println(b);
}
public booelan getB() {
return b;
}
public void setA(boolean b) {
this.b = b;
}
main:
public class main {
/**
* #param args
*/
public static void main(String[] args) {
ClassAImplA param1 = new ClassAImplA(10);
ClassA = param1;
}
}
By doing this I make ClassA interchangeable,
but I lose the capability to access the parameter int a.
Is there a way to still make it interchangeable, and still have access to int a,
or in case of ClassAImplB, the field boolean b ?
There is a way, but it's not a good idea to do, as it defeats the purpose:
ClassAImplA param1 = new ClassAImplA(10);
ClassA = param1;
if (param1 instanceof ClassAImplA) {
param1x = (ClassAImplA) param1;
System.out.println(param1x.getA());
}
But don't do this. It defeats the purpose of the pattern.
The purpose of the pattern is to use objects of type ClassA,
without having to know how they work.
The getA method is only defined in ClassAImplA,
it's an implementation detail that should not be relevant to users of the ClassA type.
They shouldn't have to know. It's hidden.
This is called good encapsulation and information hiding.
you need one more class using composition to decide which implementation is needed.
public ClassHelper{
private A a;
public ClassHelper(A a){
this.a = a;
}
public void execute() {
this.a.execute();
}
}
public class main {
/**
* #param args
*/
public static void main(String[] args) {
ClassHelper param1 = new ClassHelper(new ClassAImplA(10));
param1.execute();
//or when you need classBIMpl
param1 = new ClassHelper(new ClassAImplB(true));
param1.execute();
}
}
And about the ability to access member of implA or implB , no you cannot have that flexibilty with this patter, whole point of this pattern is that caller need not be aware of implementation details.
Define an interface for the strategy and a Factory with different overloaded methods to create the concrete instances of the classes. Of course the methods are typed to the interface instead of the concrete classes.
The interface.
public interface Strategy {
void execute();
}
The first implementation.
public class ConcreteStrategy implements Strategy {
private boolean a;
public ConcreteStrategy(final boolean a) { this.a = a; }
public void execute() {}
}
The second implementation.
public class AnotherConcreteStrategy implements Strategy {
private int a;
public AnotherConcreteStrategy(final int a) { this.a = a; }
public void execute() {}
}
The factory.
public class Factory {
public static Strategy create(final boolean a) {
return new ConcreteStrategy(a);
}
public static Strategy create(final int a) {
return new AnotherConcreteStrategy(a);
}
}
I have a requirement that is close to extending enums and since that is not possible, after doing some research online, I came up with this approach of using interfaces and making the enums extend them.
My problem is that I have a few basic types A,B and a flag for each type that says if that has to be checked. Similarly I have some extended types C... which do the same stuff after checking their flags.
Here is the code that does this
Type Interface:
public interface Type {
public String name();
}
Here is the class that uses the basic types
public class BasicChecker {
private static boolean checkA = false;
private static boolean checkB = false;
public enum BasicType implements Type {
A, B;
}
public static boolean isCheckA() {
return checkA;
}
public static void setCheckA(boolean checkA) {
BasicChecker.checkA = checkA;
}
public static boolean isCheckB() {
return checkB;
}
public static void setCheckB(boolean checkB) {
BasicChecker.checkB = checkB;
}
public static void doStuff(String message, Type type) {
if (type.name().equalsIgnoreCase(BasicType.A.name())) {
doStuff(message, isCheckA());
} else if (type.name().equalsIgnoreCase(BasicType.B.name())) {
doStuff(message, isCheckB());
}
}
protected static void doStuff(String message, boolean flag) {
if (someCheckMethod() && flag) {
doStuff(message, flag);
}
}
private static boolean someCheckMethod() {
return false;
}
}
And this is the class that uses extended types
public class ExtendedChecker extends BasicChecker {
private static boolean checkC = false;
public enum ExtendedType implements Type {
C;
}
public static boolean isCheckC() {
return checkC;
}
public static void setCheckC(boolean checkC) {
ExtendedChecker.checkC = checkC;
}
public static void doStuff(String message, Type type) {
BasicChecker.doStuff(message, type);
if (type.name().equalsIgnoreCase(ExtendedType.C.name())) {
doStuff(message, isCheckC());
}
}
}
What I am trying to solve now is to remove all the if else cases from log method. I am also trying to see if there is a better way to do this. Please ignore the statics. I do want them to be static fields and methods.
I'm having trouble understanding exactly what you're trying to do from your description, but you may find abstract methods in enums to be useful.
For example, you could add an abstract method "foo" to your enums:
public enum BasicType implements Type {
A {
public void foo(String message) {
// Do special A stuff
}
}, B {
public void foo(String message) {
// Do special B stuff
}
};
public abstract void foo(String message);
}
And you could then use that method like this:
public static void doStuff(String message, Type type) {
type.foo(message);
}
Naturally, you could put any such abstract methods in an interface you extend, if that's useful.
public class BasicChecker {
private static final Set<Type> _doCheck = Collections.newSetFromMap(new ConcurrentHashMap<Type,Boolean>());
public enum BasicType implements Type {
A, B;
}
public static boolean isCheck(Type type) {
return return _doCheck.contains(type);
}
public static void setCheck(Type type, boolean check) {
if(check) {
_doCheck.add(type);
} else {
_doCheck.remove(type);
}
}
public static void doStuff(String message, Type type) {
doStuff(message, isCheck(type));
}
}
I have method that should at the end to the same process but the can get diffrent parameters
since the need to do that process in different way
my question is this is the best way to do that assuming that this is the APIs
void action(String a,String b){
functionA();
functionB();
functionC();
}
void action(String a){
functionA();
functionC();
}
void action(String a,String B,String C){
functionA();
functionC();
functionD();
}
the reason that I ask that is as you can see I always use functionA and functionC?
There is more elegant way to do that in java?
You can share code between overloaded functions, it is very logical for overloaded function to share code between them.
//this delegates what happens to 'a' to the lower link, passing the responsibility to it along the 'chain'
void action(String a,String b){
action(a);
functionB();
}
//this delegates what happens to 'a' to the lower link, passing the responsibility to it along the 'chain'
void action(String a,String B,String C){
action(a);
functionD();
}
//this is the lowest link in your chain of responsibility, it handles the one parameter case
void action(String a){
functionA();
functionC();
}
Your question is not very clear,
but have a look at the Command Pattern. You could actually build commands from different sub-commands.
Something like this?
public class CommandExample {
private final Map<String, Command> availableCommands;
CommandExample() {
availableCommands = new HashMap<>();
List<Command> cmds = Arrays.asList(new Command[]{new CommandA(), new CommandB(), new CommandC(), new CommandD()});
for (Command cmd:cmds)
availableCommands.put(cmd.getId(), cmd);
}
public interface Command {
public String getId();
public void action();
}
public class CommandA implements Command {
#Override
public String getId() {
return "A";
}
#Override
public void action() {
// do my action A
}
}
public class CommandB implements Command {
#Override
public String getId() {
return "B";
}
#Override
public void action() {
// do my action B
}
}
public class CommandC implements Command {
#Override
public String getId() {
return "B";
}
#Override
public void action() {
// do my action C
}
}
public class CommandD implements Command {
#Override
public String getId() {
return "C";
}
#Override
public void action() {
// do my action D
}
}
public void execute(String[] input) {
for (String in: input) {
availableCommands.get(in).action();
}
}
}
I have to handle two classes with identical methods but they don't implement the same interface, nor do they extend the same superclass. I'm not able / not allowed to change this classes and I don't construct instances of this classes I only get objects of this.
What is the best way to avoid lots of code duplication?
One of the class:
package faa;
public class SomethingA {
private String valueOne = null;
private String valueTwo = null;
public String getValueOne() { return valueOne; }
public void setValueOne(String valueOne) { this.valueOne = valueOne; }
public String getValueTwo() { return valueTwo; }
public void setValueTwo(String valueTwo) { this.valueTwo = valueTwo; }
}
And the other...
package foo;
public class SomethingB {
private String valueOne;
private String valueTwo;
public String getValueOne() { return valueOne; }
public void setValueOne(String valueOne) { this.valueOne = valueOne; }
public String getValueTwo() { return valueTwo; }
public void setValueTwo(String valueTwo) { this.valueTwo = valueTwo; }
}
(In reality these classes are larger)
My only idea is now to create a wrapper class in this was:
public class SomethingWrapper {
private SomethingA someA;
private SomethingB someB;
public SomethingWrapper(SomethingA someA) {
//null check..
this.someA = someA;
}
public SomethingWrapper(SomethingB someB) {
//null check..
this.someB = someB;
}
public String getValueOne() {
if (this.someA != null) {
return this.someA.getValueOne();
} else {
return this.someB.getValueOne();
}
}
public void setValueOne(String valueOne) {
if (this.someA != null) {
this.someA.setValueOne(valueOne);
} else {
this.someB.setValueOne(valueOne);
}
}
public String getValueTwo() {
if (this.someA != null) {
return this.someA.getValueTwo();
} else {
return this.someB.getValueTwo();
}
}
public void setValueTwo(String valueTwo) {
if (this.someA != null) {
this.someA.setValueTwo(valueTwo);
} else {
this.someB.setValueTwo(valueTwo);
}
}
}
But I'm not realy satisfied with this solution. Is there any better / more elegant way to solve this problem?
A better solution would be to create an interface to represent the unified interface to both classes, then to write two classes implementing the interface, one that wraps an A, and another that wraps a B:
public interface SomethingWrapper {
public String getValueOne();
public void setValueOne(String valueOne);
public String getValueTwo();
public void setValueTwo(String valueTwo);
};
public class SomethingAWrapper implements SomethingWrapper {
private SomethingA someA;
public SomethingWrapper(SomethingA someA) {
this.someA = someA;
}
public String getValueOne() {
return this.someA.getValueOne();
}
public void setValueOne(String valueOne) {
this.someA.setValueOne(valueOne);
}
public String getValueTwo() {
return this.someA.getValueTwo();
}
public void setValueTwo(String valueTwo) {
this.someA.setValueTwo(valueTwo);
}
};
and then another class just like it for SomethingBWrapper.
There, a duck-typed solution. This will accept any object with valueOne, valueTwo properties and is trivially extensible to further props.
public class Wrapper
{
private final Object wrapped;
private final Map<String, Method> methods = new HashMap<String, Method>();
public Wrapper(Object w) {
wrapped = w;
try {
final Class<?> c = w.getClass();
for (String propName : new String[] { "ValueOne", "ValueTwo" }) {
final String getter = "get" + propName, setter = "set" + propName;
methods.put(getter, c.getMethod(getter));
methods.put(setter, c.getMethod(setter, String.class));
}
} catch (Exception e) { throw new RuntimeException(e); }
}
public String getValueOne() {
try { return (String)methods.get("getValueOne").invoke(wrapped); }
catch (Exception e) { throw new RuntimeException(e); }
}
public void setValueOne(String v) {
try { methods.get("setValueOne").invoke(wrapped, v); }
catch (Exception e) { throw new RuntimeException(e); }
}
public String getValueTwo() {
try { return (String)methods.get("getValueTwo").invoke(wrapped); }
catch (Exception e) { throw new RuntimeException(e); }
}
public void setValueTwo(String v) {
try { methods.get("setValueTwo").invoke(wrapped, v); }
catch (Exception e) { throw new RuntimeException(e); }
}
}
You can use a dynamic proxy to create a "bridge" between an interface you define and the classes that conform but do not implement your interface.
It all starts with an interface:
interface Something {
public String getValueOne();
public void setValueOne(String valueOne);
public String getValueTwo();
public void setValueTwo(String valueTwo);
}
Now you need an InvocationHandler, that will just forward calls to the method that matches the interface method called:
class ForwardInvocationHandler implements InvocationHandler {
private final Object wrapped;
public ForwardInvocationHandler(Object wrapped) {
this.wrapped = wrapped;
}
#Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Method match = wrapped.getClass().getMethod(method.getName(), method.getParameterTypes());
return match.invoke(wrapped, args);
}
}
Then you can create your proxy (put it in a factory for easier usage):
SomethingA a = new SomethingA();
a.setValueOne("Um");
Something s = (Something)Proxy.newProxyInstance(
Something.class.getClassLoader(),
new Class[] { Something.class },
new ForwardInvocationHandler(a));
System.out.println(s.getValueOne()); // prints: Um
Another option is simpler but requires you to subclass each class and implement the created interface, simply like this:
class SomethingAImpl extends SomethingA implements Something {}
class SomethingBImpl extends SomethingB implements Something {}
(Note: you also need to create any non-default constructors)
Now use the subclasses instead of the superclasses, and refer to them through the interface:
Something o = new SomethingAImpl(); // o can also refer to a SomethingBImpl
o.setValueOne("Uno");
System.out.println(o.getValueOne()); // prints: Uno
i think your original wrapper class is the most viable option...however it can be done using reflection, your real problem is that the application is a mess...and reflection is might not be the method you are looking for
i've another proposal, which might be help: create a wrapper class which has specific functions for every type of classes...it mostly copypaste, but it forces you to use the typed thing as a parameter
class X{
public int asd() {return 0;}
}
class Y{
public int asd() {return 1;}
}
class H{
public int asd(X a){
return a.asd();
}
public int asd(Y a){
return a.asd();
}
}
usage:
System.out.println("asd"+h.asd(x));
System.out.println("asd"+h.asd(y));
i would like to note that an interface can be implemented by the ancestor too, if you are creating these classes - but just can't modify it's source, then you can still overload them from outside:
public interface II{
public int asd();
}
class XI extends X implements II{
}
class YI extends Y implements II{
}
usage:
II a=new XI();
System.out.println("asd"+a.asd());
You probably can exploit a facade along with the reflection - In my opinion it streamlines the way you access the legacy and is scalable too !
class facade{
public static getSomething(Object AorB){
Class c = AorB.getClass();
Method m = c.getMethod("getValueOne");
m.invoke(AorB);
}
...
}
I wrote a class to encapsulate the logging framework API's. Unfortunately, it's too long to put in this box.
The program is part of the project at http://www.github.com/bradleyross/tutorials with the documentation at http://bradleyross.github.io/tutorials. The code for the class bradleyross.library.helpers.ExceptionHelper in the module tutorials-common is at https://github.com/BradleyRoss/tutorials/blob/master/tutorials-common/src/main/java/bradleyross/library/helpers/ExceptionHelper.java.
The idea is that I can have the additional code that I want to make the exception statements more useful and I won't have to repeat them for each logging framework. The wrapper isn't where you eliminate code duplication. The elimination of code duplication is in not having to write multiple versions of the code that calls the wrapper and the underlying classes. See https://bradleyaross.wordpress.com/2016/05/05/java-logging-frameworks/
The class bradleyross.helpers.GenericPrinter is another wrapper that enables you to write code that works with both the PrintStream, PrintWriter, and StringWriter classes and interfaces.