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.