Cao Felix
Cao Felix

Reputation: 329

Java implements different methods in two classes using one interface

I have a Java question and I can't see how I can implement the methods correctly. I am not very good with architecture.

Data Manager interface class:

public interface DataManager {
   public void readData();
   public void writeData();
}

Data abstract class:

public abstract class Data implements DataManager {
    @Override
    public void readData() {};
    @Override
    public void writeData() {};
}

Data Reader class:

public class DataReader extends Data {
   // I want to implement the readData() here
}

Data Writer class:

public class DataWriter extends Data {
   // I want to implement the writeData() here
}

If I want to implement the readData() and writeData() separately in two different classes with only one interface, is it possible? I don't know why I am doing this way. Maybe it just looks cleaner and easier when I add more methods to the reader or writer class. Should I implement everything in just one single class?

I want this library to allow users using the manager object to have access for data reading and writing. But for implementation, I don't know how I can do it correctly.

Upvotes: 1

Views: 3034

Answers (4)

Cao Felix
Cao Felix

Reputation: 329

After a lot of modification, so I do it this way and I think it fits my solution.

Data Manager interface class:

public interface DataManager {
   public Data readData(); // from database
   public void writeData(); // to database
}

DataConnector class:

public class DataConnector implements DataManager {
   DataCreate creator = new DataCreate();
   @Override
   public Data readData() {
       return creator.readData();
   };
   @Override
   public void writeData() {
       creator.writeData();
   };
   public Connection getConnection() {...};
   public void close() {...};
}

Data Create class:

public class DataCreate {
   public void readData() {
      new DataReader().readData();
   }

   public void writeData() {
      new DataWriter().writeData();
   }
}

Data Reader class:

public class DataReader {
   // I want to implement the readData() here
   public Data readData(){...};
}

Data Writer class:

public class DataWriter {
   // I want to implement the writeData() here
   public void writeData(){...};
}

Example:

DataManager manager = new DataConnector();
manager.readData();
manager.writeData();

So clients will only use methods from the manager public interfaces to do database reading and writing. Edward Peters mentioned composition to me and I did not understand it at that time. I am not very sure if what I am doing now is what composition should be doing. I think the credit should go to him. Thanks for the help.

Upvotes: 0

Erik Uggeldahl
Erik Uggeldahl

Reputation: 1146

Looks like you've stumbled on the reason for the "Interface Segregation Principal". https://en.wikipedia.org/wiki/Interface_segregation_principle

While DataReader and DataWriter may seem related at first, and it might look like it makes sense to group them into your common interface DataManager, the job of reading and writing is quite different, and warrants a separation into two interfaces, e.g. IReader and IWriter.

Suppose you have a class that needs both a reader and a writer together, and so your DataManager interface makes sense. However, there's nothing stopping you from passing two objects, one of type IReader and one of type IWriter even if they're the same class underneath. But it seems you've already separated them into DataReader and DataWriter, which is good. As one of the other answers suggests, this is the application of the Single Responsibility Principal.

Upvotes: 3

RobotKarel314
RobotKarel314

Reputation: 417

If you're only having a certain subclass implement each method, you don't need DataManager or Data. Just have DataReader and DataWriter contain only the methods they need, like so:

public class DataReader {
   public void readData() {...}
}
...
public class DataWriter {
   public void writeData() {...}
}

The whole reason of extending and implementing is to either clean up code, or allow for overriding another method. The way you're doing it does neither, so why not just keep it simple?

Upvotes: 0

Lew Bloch
Lew Bloch

Reputation: 3433

A best practice in programming is the "Single Responsibility Principle". A reader is not a writer, so it shouldn't be a subtype of a DataManager that requires its implementors to be both. By defining an abstract class that creates empty methods for the entire interface, you've also lost the value of having an interface. An interface is a contract that every implementor must /be-a/ case of its supertype. A reader is not a candidate to /be-a/ reader and a writer. You want a separate reader and writer interface, and have your readers implement one, writers the other, and datamanagers can implement both.

Also, don't use Reader and Writer in names for types that aren't subtypes of java.io.Reader and java.io.Writer, respectively. Since you're thinking of "data managers", maybe you could use ReadManager and WriteManager, or something like that, that lets people know you aren't using the standard Reader and Writer hierarchies.

Upvotes: 2

Related Questions