0
votes

Currently I have 3 classes in which most of the variables are same. All the variables have getter and setter. I need to create the object of the class based on the datatype variable Year provided and pass that object in the more than ten methods. Lets Take a Example.

We have three Classes ClassA,ClassB,ClassC. If we pass the year 2017 then i need the object of ClassA. If we pass the year 2016 then i need the object of ClassB and for all other year we need the object of ClassC.

Then after we need to pass that object in the all 10 Methods. Let take an exmaple of 2 methods.

public void method1(int a, int b, object of classA/B/C).

public void method2(int a, int b, object of classA/B/C).

Both the methods working on the object and setting some variable in object.

But one problem is that i don't want to extend class or implement interface in the ClassA,ClassB,ClassC because the ClassA,ClassB,ClassC are made from the XSD file and i don't want to change in the classes.

Please let me know the Design Pattern that perfect for my requirement.

4
a simple conditional statement will doStultuske
@Stultuske , If i don't need to pass that object of class in the method then this will work but i need to pass the object of class in the method , that's why i need design pattern. That can help me to do this task.RSCode
Why don't you want to use inheritance? I have never written a production grade without using inheritance.Avinash
@Robin since you know the types possible, again: a simple conditional statement will doStultuske
@Avinash , I don't want to use Inheritance because the ClassA,ClassB,ClassC are made from the XSD file and i don't want to change in the classes. I need the super class that inherited the properties of those classes and do the remaining work.RSCode

4 Answers

1
votes

To create instance of any of the classes A/B/C based on year passed, you can go for factory pattern. That should be pretty straight forward.

Second part of your problem is to pass object of the classes A, B, C to some methods of yours. This can be done in two ways.

If your classes are related i.e. they implement some common interface or abstract class , you can code your methods to accept the interface or abstract class i.e

public class A implements ICommonInterface {}
public class B implements ICommonInterface {}
public class C implements ICommonInterface {}

public void method1(int a, int b, ICommonInterface object){}

or they extend some common class

public class A extends CommonClass {}
public class B extends CommonClass {}
public class C extends CommonClass {}


public void method1(int a, int b, CommonClass object){}

If it's none of the case, you can make your methods to accept generic types

public void method1(int a, int b, T object){}

Since all classes have same variables, you should not have any problems working with either approach.

0
votes

If you are trying to learn about design patterns, then you need a creational pattern that abstracts the object instantiation. This can be achieved by a Factory pattern.

Your second requirement defeats the purpose of using the factory pattern since the caller(one who requests object via factory) might still need to know the actual instance type inorder to pass the arguments to the 10(already well-known methods)

0
votes

Not using an interface or extending another class really limits what the compiler can do to ensure your code is safe.

You could solve the problem by creating the 10 methods so that they receive a plain Object and then using reflection to assign the values you need.

You should, however, check for invalid arguments being passed on to your methods (i.e.: check that the class is within a list of acceptable classes) or at least ensure the object you receive has the appropriate members (setters).

0
votes

Here's what I would do:

Depending on a set of condition, I would build a wrapper implementing a common interface:

public interface CommonInterface {
    public String getVar1();
    public void setVar1(String value);
    public String getVar2();
    public void setVar2(String value);
    // ...
}

With the same getters and setters as in ClassA, ClassB and ClassC:

public class ClassA {
    private String var1;
    private String var2;

    public String getVar1() {
        return var1;
    }

    public void setVar1(String value) {
        var1 = value;
    }

    public String getVar2() {
        return var2;
    }

    public void setVar2(String value) {
        var2 = value;
    }
}

You can then dynamically create a wrapper implementing the CommonInterface. You can use a factory method to select one object or the other depending on the year:

public static CommonInterface getWrapper(ClassA a, ClassB b, ClassC c,
        int year) {
    if (year >= 2017) {
        return wrap(a, CommonInterface.class);
    } else if (year >= 2016) {
        return wrap(b, CommonInterface.class);
    } else {
        return wrap(c, CommonInterface.class);
    }
}

The wrap method would look like this:

private static <T> T wrap(final Object obj, Class<T> intf) {
    final Class<?> clazz = obj.getClass();
    ClassLoader cl = Thread.currentThread().getContextClassLoader();
    Object result = Proxy.newProxyInstance(cl,
            new Class<?>[] {intf},
            (proxy, method, args) -> {
                Method actual = clazz.getMethod(
                        method.getName(), method.getParameterTypes());
                return actual.invoke(obj, args);
            });
    return intf.cast(result);
}