I have two classes that both take the same type of object as an argument, but then call a different method on that object to obtain another object (the obtained object's type is also different in both classes) that is used extensively throughout the classes in different methods. Now, some of these methods are identical between the two classes, so I thought that it would be wise to put them in a subclass. However, since the methods are dependent on the object that was obtained by calling a different method on the object given as an argument to the constructors, i can't just copy the constructors from subclasses to the superclass. I'm uncertain how can the superclass obtain the required object. It seems that my potential superclass `Server` would be dependent on its subclasses, which even sounds wrong.
Here's an illustrative code of the problem:
class ServerOne() {
Connector connector;
public ServerOne(Conf conf) {
Conf.ServerOneConf config = conf.getServerOneConf();
connector = config.getConnector(); //
}
// a lot of methods that use connector
}
class ServerTwo() {
Connector connector;
public ServerTwo(Conf conf) {
Conf.ServerTwoConf config = conf.getServerTwoConf(); // notice that it uses a different method for obtaining the configuration. Also, the obtained object is of a different type than the configuration object that was obtained in the ServerOne constructor.
connector = config.getConnector();
}
// a lot of methods that use connector
}
class Server() {
// would like to implement some common methods that use connector.
// need to get an instance of the Connector to this class.
}
Thank you very much for your help :)
There may be reasons to subclass your Server class, but how to get the connector probably isn't a reason for subclassing. Make a strategy to handle getting a Connector:
interface ConnectorStrategy {
Connector retrieveConnector(Conf conf);
}
with implementations like
class ServerOneConnectorStrategy implements ConnectorStrategy {
public Connector retrieveConnector(Conf conf) {
return conf.getServerOneConf().getConnector();
}
}
and pass this in to the Server object when you create it.
Or if you need the hierarchy, use the template method pattern:
abstract class Server {
abstract Connector retrieveConnector(Conf conf);
void initializeConnector(Conf conf) {
...
connector = retrieveConnector(conf);
}
...
}
class ServerOne extends Server {
public Connector retrieveConnector(Conf conf) {
return conf.getServerOneConf().getConnector();
}
}
How about making Server as an abstract class and extends ServerOne and ServerTwo from it.
Like this:
public abstract class Server() {
Connector connector;
public Server() {
Configuration config = conf.getServerTwoConf();
connector = config.getConnector();
}
...
}
class ServerOne() extends Server{
...
}
class ServerTwo() extends Server{
...
}
This is a perfect case for extending a superclass. The object you are populating in both constructors is of the same type - not the same data. When you create a ServerOne, it will populate the object held in the superclass the way you currently do. Then, the common methods in the superclass can now operate on this object that is populated.
Put your shared methods in the super class
class Server() {
Connector connector;
public Server(Conf conf) {
Configuration config = conf.getServerConf();
connector = config.getConnector(); //
}
// your methods
}
and then just use the super() call in the constructor of your subclasses. They can easily inherit the methods of your super class without having to write them again.
class ServerOne() extends Server {
public ServerOne(Conf conf) {
super(conf);
}
}
Related
I have a BasePersister that builds a complex persistence client in it's constructor, using Dagger:
public abstract class BasePersister {
#Getter
private PersistenceClient client;
public BasePersister() {
this.client = DaggerPersistenceClientComponent.create().getClient();
}
public abstract void persist(String data);
protected void helper() {
System.out.println("I am a helper");
}
}
The idea is that child persister classes can just extend the base class and perform its persistence logic with the client. An example child class:
public class SpecialPersister extends BasePersister {
public void persist(String data) {
// do stuff with the client
getClient().persist(data);
// use the shared helper
helper();
}
}
Moving the client instantiation within the base class constructor was ideal because in my PersisterFactory, I can simply invoke statements like new SpecialPersister(); the constructor doesn't take any arguments, doesn't need Dagger to instantiate and the factory is completely unaware of any clients.
I'm having trouble testing these child classes and I'm suspecting it has to do with my design choice of secretly instantiating clients within the base constructors.
More specifically, in my SpecialPersisterTest class, I can't do Spy(SpecialPersister) as this invokes the base constructor, which then instantiates my complex clients (giving me an error). I somehow need to mock this super-constructor call so that it doesn't actually invoke client instantiation, which has complex network calls etc.
Ideally, I can do a simple test such as checking:
def "my ideal test"() {
given:
specialPersister.persist(validData)
then:
1 * specialPersister.getClient()
and:
1 * specialPersister.helper()
}
Moving the client instantiation within the base class constructor was ideal because in my PersisterFactory, I can simply invoke statements like new SpecialPersister(); the constructor doesn't take any arguments, doesn't need Dagger to instantiate and the factory is completely unaware of any clients.
I'm having trouble testing these child classes and I'm suspecting it has to do with my design choice of secretly instantiating clients within the base constructors.
This design choice is the issue. If you want the code to be testable without making calls on the real client, you will need to be able to stub your client. One option for this is to pass the PersistenceClient in at instantiation.
Since you are using a factory pattern, your factory can provide it without worrying about the details elsewhere in your code. It should know how to create Persister objects, regardless of if it needs to know the details about the client - coupling at this level should be encouraged. You may also want your factory to take the argument, as well, so that a Persister from the factory can be tested.
public abstract class BasePersister {
private PersistenceClient client;
public BasePersister(PersistenceClient client) {
this.client = client;
}
}
public class SpecialPersister extends BasePersister {
public SpecialPersister(PersistenceClient client) {
super(client);
}
}
public class PersisterFactory {
// pass in the client once to a PersisterFactory instance
private PersistenceClient client;
public PersisterFactory(PersistenceClient client) {
this.client = client;
}
public SpecialPersister createSpecialPersister() {
return new SpecialPersister(client);
}
}
// elsewhere
PersisterFactory persisterFactory = new PersisterFactory(DaggerPersistenceClientComponent.create().getClient());
// ...
BasePersister persister = persisterFactory.createSpecialPersister();
I have a AbstractBaseRepository. All my Repositories extends from this class. I created another class RepositoryFactory to create any instance of Repository. Due to early binding of static method, I am facing problem.
public abstract class AbstractBaseRepository {
public static <T extends AbstractBaseRepository> T getNewInstance(EntityManagerFactory entityManagerFactory) {
throw new RuntimeException("Override and provide valid initialization");
}
...
}
public class RepositoryFactory {
public static <T extends AbstractBaseRepository> T getRepository(Class<T> cls) {
return T.getNewInstance(entityManagerFactory);
}
...
}
an example subclass
public class DeviceModelRepo extends AbstractBaseRepository {
public static DeviceModelRepo getNewInstance(EntityManagerFactory entityManagerFactory) {
return new DeviceModelRepo(entityManagerFactory);
}
...
}
Whenever I call getRepository() with a valid subclass of AbstractBaseRepository, runtime exception is thrown. This is due to early binding of static methods. During compile time, getNewInstance gets bound with AbstractBaseRepository rather than at runtime with actual type of the class. Any good workarounds?
My first suggestion is using Spring. It is very easy to get a list of all beans created with a certain interface.
Also, if you think of your Repository instances as a type of "plug-in" you might see how Java's ServiceLoader class can help.
Also, another approach is to use a switch statement in the factory and create the instances for each case rather than using static methods on the Repository subclasses.
Finally, I don't recommend reflection solutions but there are ways to load the class based on its name and reflectively creating a new instance.
But overriding static methods is not possible.
What I have understood by seeing your code is that you want to have different implementations of AbstractBaseRepository such as DeviceModelRepo. Then you want a factory class to create the instance of specific implementation of AbstractBaseRepository. Here the major problem is you try to overriding static methods which can never be overwritten but subclass will hide the parent implementation. Please don't use static method for overriding. You can change your implementation as given below and this issue will be resolved.
public abstract class AbstractBaseRepository {
public AbstractBaseRepository(EntityManagerFactory entityManagerFactory){
...
}
//removed method getNewInstance(EntityManagerFactory entityManagerFactory)
...
}
Then below implementation for subclass.
public class DeviceModelRepo extends AbstractBaseRepository {
public DeviceModelRepo(EntityManagerFactory entityManagerFactory) {
super(entityManagerFactory);
...
}
//removed method getNewInstance(EntityManagerFactory entityManagerFactory)
...
}
Now I am providing you two implementation of factory class.
One is having different method for each of implementation, such as getDeviceModelRepository().
Another solution is to use reflection and get repository instance by passing the implementation repository class.
public class RepositoryFactory {
//Solution-1, create separate method for each of repository like below
public static AbstractBaseRepository getDeviceModelRepository() {
return new DeviceModelRepo(entityManagerFactory);
}
//Solution-2, use reflection to get instance of specific implementation
//of AbstractBaseRepository
public static <T extends AbstractBaseRepository> T
getRepository(Class<T> repoClass) throws Exception{
return repoClass.getConstructor(EntityManagerFactory.class)
.newInstance(entityManagerFactory);
}
...
}
With reflection solution, you can get the repository instance as given below.
RepositoryFactory.getRepository(DeviceModelRepo.class)
I have a Class called Module which has a Method onEnable();
Now i have a class called Config and want to make the onEnable(); method private because there is a predefined acting and a class extending Config should'nt be allowed to change the behaviour.
Is there any way to do this?
Example
class Module{
public void onEnable(){
}
}
A class extending Module which is allowed to use onEnable:
class HelloWorldModule{
#Override
public void onEnable(){
System.out.println("Hello, World!");
}
}
Now the config Class, where i want that onEnable is private so that Classes which extend Config cannot! Override onEnable:
class Config{
#Override
private void onEnable(){
}
}
So NOW, a class named ProgrammConfig which extends Config cannot override onEnable.
However, this is not working because you cannot override a public method to a private method.
By declaring a method as public, you are saying that it should be possible to call said method on every instance of this class, including subclasses. Declaring a method as private in a subclass doesn't make sense, and is thus not allowed.
Now, if you're concerned about subclasses overriding the method, you can declare the method as final to prevent this:
class Config extends Module{
#Override
public final void onEnable(){}
//Whatever
}
You cannot solve this using inheritance. If Config is a subclass of Module, then it must provide all functions of Module with (at most) the same access restrictions. Think of a subclass as a specialized version of the superclass: It can do everything the superclass can, likely more, but never less.
Still you can implement a Config class as desired. Just skip subclassing, and instead use a private field of type Module like so:
class Config {
private Module module;
public Config() {
module = new Module();
}
public int SomeFunctionFromModuleYouWantToExpose() {
return module.SomeFunctionFromModuleYouWantToExpose();
}
// ...
}
I have got an interface that defines some service methods for data retrieval:
public interface DataReceiver {
public Data getData();
}
Then i have a class that implements this interface and loads the data through a connection. I supply this connection using constructor injection:
public class ConnectionDataReceiver implements DataReceiver {
private Connection connection;
public ConnectionDataReceiver(Connection connection) {
this.connection = connection;
}
public Data getData() {
return connection.query("blabla");
}
}
This works pretty nicely. I can instantiate my ConnectionDataReceiver objects using the constructor, or i could add a factory method/class that extends the usability by providing an option to select a config file for connection setup. I then use my new class through my interface, so i can easily swap out the implementation (like loading the data from a file instead of a connection).
But what if i want to change my connection during runtime, without instantiating a new ConnectionDataReceiver? I would have to add getters and setters for my class. But since they are not part of my public service definition, i can't put them in my interface. I could use the implementation object in my code to set a new connection, but it feels pretty awkward hanging onto a reference to the original object only for maybe changing the connection object:
ConnectionDataReceiver conDataRec = new ConnectionDataReceiver(myConnection);
DataReceiver dataRec = conDataRec;
// use dataRec
conDataRec.setConnection(myNewConnection);
// use dataRec again
In this example it would be the easiest way to just instantiate a new ConnectionDataReceiver and just reassign dataRec, but what if the instantiation of my object is really expensive? How do i give my implementation classes additional functionality while still being able to use my old service interface? Or is it generally frowned upon changing data at runtime, when the interface doesn't define that functionality?
What you can do is that adding following two simple methods in your interface:
public void setProperty(String name, Object value);
public Object getProperty(String name);
Now with the help of these two simple methods, you may configure as many additional functionalities as you want in your implementation classes without adding a new method for a new feature (of your implementation class) in your super type.
This pattern is used in following interface:
com.ibm.msg.client.jms.JmsQueueConnectionFactory
The interface has setCharProperty, setDoubleProperty, setFloatProperty etc so that when they release a new implementation they do not have to modify the interface.
My version:
Interface
public interface DataReceiver
{
public Data getData();
}
Implementation
public class ConnectionDataReceiver implements DataReceiver
{
private Connection connection;
public ConnectionDataReceiver(Connection connection)
{
this.connection = connection;
}
public Data getData()
{
return connection.query("blabla");
}
}
Interface using in business layer, here method setReceiver will assign new implementation of interface in run-time.
public class SomeBusinessLogic
{
private DataReceiver receiver;
public SomeBusinessLogic(DataReceiver receiver)
{
this.receiver = receiver;
}
public void setReceiver(DataReceiver receiver)
{
this.receiver = receiver;
}
}
With this approach you can change implementation of DataReceiver in run-time
While working on an web-application , I need to get a set of classes at few steps and I am thinking to separate this logic to a simple Factory so as based on the Class type We can create class instance as well init it with default values.
Current structure of Class hierarchy is
public interface DataPopulator<Source,Target>{
// some method decaration
}
Abstract class
public abstract class AbstractDataPopulator<Source,Target> implements DataPopulator<Source, Target>{
// some common implimentation
}
And now classes which will be used as actual implementations like
Type1Populator extends AbstractDataPopulator.
Type2Populator extends AbstractDataPopulator.
Each of these implementation needs a set of common dependencies based on what functionality is being executed by those Populators.
As of Now I am creating instance with new and than filling those dependencies with simple setter methods.
I am thinking about creating a simple factory pattern like
public interface PopulatorFactory{
<T extends Object> T create(String className) throws Exception;
<T extends Object> T create(Class populatorClass) throws Exception;
}
Abstract class
public abstract class DefaultPopulatorFactory impliments PopulatorFactory{
public <T> T create(final Class populatorClass) throws Exception{
return Class.forName(populatorClass);
}
// other method.
}
Implementation classes
public Type1PopulatorFactory extends DefaultPopulatorFactory {
public <T> T create(final Class populatorClass) throws Exception{
final T populator= super.create(populatorClass);
}
}
I also want to initialize newly created instances with some default values specific to each implementation, but I'm not sure what's the best way to do this?
Should I define another method say initDefaults?
What is the best way to pass those dependencies to these poulators.
Is the approach outlined by me fine or is it overly complicated?
In cases when you are building not-so-trivial objects it is usually better to use the Builder pattern instead of a Factory.
In your case if you don't need external data sources you can simply write constructors for your classes where you can supply the default values and get rid of the contraption in your question.
If you use the Builder pattern you can simplify your framework by using a Builder object for the common data and a SomeOtherBuilder which extends from Builder and adds the custom values of the specialized implementation. You can make your classes constructors which are taking a Builder object.
public class Builder {
// your fields go here
}
public class SomeOtherBuilder extends Builder {
// your specialized fields go here
}
public class YourClass {
public YourClass(Builder builder) {
// construct it here
}
}
You can also make your classes generic with using something like T extends Builder.