I have an interface Itest
and ClassA
& ClassB
are implementing this interface. testA
& testB
are methods in these classes respectively.
testA(String a, String b, String c, D d, E e)
testB(String a, String b, String c, F f, G g)
Here D
, E
, F
, G
are custom data types (related to databases). I simplified the methods actually they have more number of parameters.
I need to make a generic method in testAB
in Itest
interface and implement that in both classes rather than having their own method.
testAB(String a, String b, String c, D d, E e, F f, G g)
As the number of parameters is more, generic method testAB
will be pain for the user as he has to pass so many null
values.
Is this a usecase for Bulider Design Pattern?
If yes, how to achieve this using this design pattern?
Looks like the core requirement that you have is that you don't want the client to be passing additional parameters when they are not required. You can solve your problem using plain old method overloading
:
Alter your ITest
interface to have a single method called test
public interface ITest {
public void test(String a,String b,String c,D d,E e,F f,G g);
}
Alter A
as follows :
public class A implements ITest {
//this is an overload - v1
public void test(String a,String b,String c,D d,E e) {
//dispatch the call to the overriden method
test(a,b,c,d,e,null,null);
}
//this is an overload - v2
public void test(String a,String b,String c,E e,F f) {
//dispatch the call to the overriden method
test(a,b,c,null,null,e,f);
}
@Override
//this is an overriden method - v3
public void test(String a,String b,String c,D d,E e,F f,G g) {
if(d!=null && e!=null) {
//use a,b,c,d,e and do something
}
if(f!=null && g!=null) {
//use a,b,c,f,g and do something
}
}
}
Now the client code can call whichever overloaded form they want without the need to pass null
. Your overloaded methods will simply dispatch the call to a common method (which gives you the advantage of code reuse):
classAObj.test("1","2","3",new D(),new E());//calls overloaded method - v1
classAObj.test("1","2","3",new F(),new G());//calls overloaded method - v2
classAObj.test("1","2","3",new D(),new E(),new F(),new G());//calls overriden method - v3
Notice how the client code does not have to worry about passing additional parameters when they are not required. Also notice how clean the client calls look. Similar changes can be made in B
as well.
1. You have an option to make ITest
an abstract class. This will allow you to make the test
method in it have the protected
access specifier. The reason for wanting a protected
access specifier is to restrict client classes from being able to access the method and always go through the overloaded forms instead. This is an add-on feature you can consider implementing in the future if you are stuck with using an interface
at the moment.
2. You could also take advantage of Generics
to avoid the need to write a new class every-time a new object type is introduced but as you can see from the other answers, this can easily complicate your code to a great extent. You could also add the overloaded methods to ITest
interface to make it a part of its contract. However, I am deliberately leaving these parts out of my answer because the crux of your problem can be solved by using overloading
.
3. The Builder
pattern is a creational pattern. It's an overkill in this particular case since classes such as D
,E
,F
and G
are domain objects. Class A
and B
don't really depend on them in the real sense but use them as a source of data instead.
Yep here you could use the builder pattern. You would like to have objects holding the information passed to your methods.
These objects could be created with an internal builder, while the fields may hold default values. Here a small example how this could look like.
ParamTestA<D, E> paramA = new ParamTestA<>.Builder(a, b, c).setD(d).setE(e).build();
testA(paramA);
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