Suppose the following (slightly pseudo-code for brevity):
class Basic
{
String foo;
}
class SomeExtension extends Basic
{
String bar;
}
class OtherExtension extends Basic
{
String baz;
}
class BasicService
{
Basic getBasic()
{
}
}
class SomeExtensionService extends BasicService
{
SomeExtension getSomeExtension()
{
}
}
class OtherExtensionService extends BasicService
{
OtherExtension getOtherExtension()
{
}
}
What would be the most idiomatic, elegant way to implement the get-() service methods with the most possible code reuse?
Obviously you could do it like this:
class BasicService
{
Basic getBasic()
{
Basic basic = new Basic();
basic.setFoo("some kind of foo");
return basic;
}
}
class SomeExtensionService
{
SomeExtension getSomeExtension()
{
SomeExtension someExtension = new SomeExtension;
Basic basic = getBasic();
someExtension.setFoo(basic.getFoo());
someExtension.setBar("some kind of bar");
return someExtension;
}
}
But this would be ugly if Basic has a lot of properties, and also you only need one object, as SomeExtension already inherits Basic. However, BasicService can obviously not return a SomeExtension object.
You could also have the get methods not create the object themselves, but create it at the outermost level and pass it to the method for filling in the properties, but I find that too imperative.
(Please let me know if the question is confusingly formulated.)
EDIT: Okay, so it was. I'll try to explain it better. Say you have two model classes, A and B. You also have two classes for returning objects of class A and B (from a database for instance, with information scattered all over so any ORM doesn't apply). Now, say A and B contains a lot of overlapping information, so it makes sense to refac开发者_如何学Gotor into a superclass C and let A and B extend from it. However, the service classes are still particular to A and B and need to duplicate the code for reading the overlapping information. How could you refactor these into a service class C?
I would add constructor to A and B which accepts C and sets the fields accordingly. The advantage over your suggested solution is that your ExtensionServices don't have to know about basic fields.
It looks like you're setting default values to your Basic (and children) objects. It's probably best to do that in their constructors.
public class Basic
{
protected String foo;
// and other properties
public Basic()
{
foo = "some kind of foo";
// assign defaults to all other properties
}
}
public class SomeExtension extends Basic
{
protected string bar;
public SomeExtension()
{
super(); // set the default properties of the base class
bar = "some kind of bar";
}
}
Remember to call super() in the child constructors so that the inherited properties will also be assigned default values.
public class BasicService
{
public Basic getBasic()
{
return new Basic();
}
}
public class ExtensionService extends BasicService
{
@Override
public Basic getBasic()
{
return new SomeExtension();
}
}
At least with this structure, you eliminate having to instantiate two objects in ExtensionService, and you actually don't set default values in the service classes. Since SomeExtension is a child of Basic, you can return a SomeExtension at the end of a function whose declared return type is Basic.
精彩评论