Java is the right way to delegate methods

My program receives information from an external source (maybe a file, a database, or something else that I can solve in the future).

I want to define an interface with all my data needs and classes that implement it (for example, a class for receiving data from a file, another for the database, etc.).

I want the rest of my project not to care about where the data comes from, nor do I need to create any object to receive the data, for example, to call "DataSource.getSomething ();"

To do this, I need a DataSource to contain an interface type variable and initialize it using one of the concrete implementations and expose all its methods (which come from the interface) as static methods.

So, let's say the name of the interface is K, and specific implementations are A, B, C.

How I do it today:

public class DataSource { private static K myVar = new B(); // For **every** method in KI do something like this: public static String getSomething() { return myVar.doSomething(); } ... } 

This is very bad, since I need to copy all the interface methods and make them static so that I can delegate it to myVar and many other obvious reasons.

What is the right way to do this? (maybe there is a design template for it?)

** Note. Since this will be the basis of many other projects, and I will use these calls from thousands (if not tens of thousands) of lines of code, I insist that it be as simple as "DataSource.getSomething ();", I do not want anything like this "DataSource.getInstance (). GetSomething ();" **

Edit: I was asked to use a DI infrastructure such as Guice, does this mean that I will need to add DI code to each entry point (that is, the "main" method) in all my projects, or is there a way to do this once for all of projects

+5
source share
3 answers

Classes using your data source must access it through the interface, and the correct instance is provided to the class at build time.

So first of all, make the DataSource interface:

 public interface DataSource { String getSomething(); } 

Now a specific implementation:

 public class B implements DataSource { public String getSomething() { //read a file, call a database whatever.. } } 

And then your calling class looks like this:

 public class MyThingThatNeedsData { private DataSource ds; public MyThingThatNeedsData(DataSource ds) { this.ds = ds; } public doSomethingRequiringData() { String something = ds.getSomething(); //do whatever with the data } } 

Elsewhere in your code, you can instantiate this class:

 public class Program { public static void main(String[] args) { DataSource ds = new B(); //Here we've picked the concrete implementation MyThingThatNeedsData thing = new MyThingThatNeedsData(ds); //And we pass it in String result = thing.doSomethingThatRequiresData(); } } 

You can take the final step using the Injection Dependency framework like Spring or Guice if you want a fantasy.

Bonus points: in your unit tests, you can instead provide the DataSource function for the layout / stub, and your client class will not be wiser!

+7
source

I want to concentrate in my answer to one important aspect in your question; You wrote:

Note. I insist that it is just like "DataSource.getSomething ();", I don't want anything like "DataSource.getInstance (). GetSomething ();"

Thing: simplicity is not , measured by the number of characters. Simplicity comes from good design; and good design comes from the following best practices .

In other words: if you think that DataSource.getSomething () is “simpler” than something that uses (for example) dependency injection “magically”, it provides you with an object that implements certain interfaces; then: you are wrong!

It is the other way around: these are divided problems: on the one hand; you must declare an interface that describes the necessary functions. On the other hand, you have client code that needs an object of this interface. This is all you should focus on. The step of "creating" this object; and making it available to your code may look more complicated than just calling a static method; but I guarantee you: after the answer, Paolo will make your product better .

Sometimes it’s easy to do the wrong thing!

EDIT: one template I'm using:

 interface SomeFunc { void foo(); } class SomeFuncImpl implements SomeFunc { ... } enum SomeFuncProvider implements SomeFunc { INSTANCE; private final SomeFunc delegatee = new SomeFuncImpl(); @Override void foo() { delegatee.foo(); } 

This template allows you to write client code, for example

 class Client { private final SomeFunc func; Client() { this(SomeFuncProvider.INSTANCE); } Client(SomeFunc func) { this.func = func; } 

Value:

  • There is good (singleton-correctway) access to the object, providing you with your functionality.
  • The impl class is fully tested modulo
  • Client code uses dependency injection and therefore is also fully tested at the level of
+2
source

My program receives information from an external source (maybe a file, a database, or something else that I can solve in the future).

This is the thought behind the templates, such as a Data Access Object (short DAO) or the Repository template. The difference is blurry. Both are an abstraction of a data source behind a single interface. A common approach is to have one DAO / Repository class for each business object or database. It is up to you if you want all of them to do the same (for example, CRUD methods) or to be specific using special requests, etc. In Java EE, templates are most often implemented using the Java Persistence API (short JPA).

To do this, I need a DataSource to contain a variable of type interface and initialize it using one of the specific implementations,

For this initialization, you do not want to know or define a type in use classes. This is where Inversion Of Control (short IOC) comes into play. An easy way to archive is to include all the dependencies in the constructor parameters, but this way you only move the problem one step. In the context of Java, you often hear the term Context and Attachment Dependency (Short CDI), which is basically an implementation of the IOC idea. In particular, Java EE has a CDI package that allows you to enter class instances based on their implemented interfaces. Basically, you don't call any constructors when using CDI efficiently. You define the dependencies of your class using annotations.

and set all its methods (which come from the interface)

It's a delusion. You want it to display only a specific interface. All other public methods in the class are irrelevant and are intended only for testing or in rare cases when you want to use certain behavior.

like static methods.

Having state classes with a static method is only an antipattern. Since your data source classes must contain a reference to the underlying data source, they have state. However, the class needs a private field. This makes using static methods impossible. In addition, static classes are very difficult to test and do not behave well in multi-threaded environments.

+1
source

All Articles