Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java - correct way to delegate methods

My program gets information from an external source (can be a file, a database, or anything else I might decide upon in the future).

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

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

For that I need DataSource to contain a variable of the type of the interface and initialize it with one of the concrete implementations, and expose all of its methods (that come from the interface) as static methods.

So, lets say the interface name is K, and the concrete implementations are A,B,C.

The way I do it today is:

public class DataSource  {
    private static K myVar = new B();

    // For **every** method in K I do something like this:

    public static String getSomething() {
          return myVar.doSomething();
    }

    ...
}

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

What is the correct way to do it? (maybe there is a design pattern for it?)

**Note - since this will be the backbone of many many other projects and I will use these calls from thousands (if not tens of thousands) code lines, I insist on keeping it simple like "DataSource.getSomething();", I do not want anything like "DataSource.getInstance().getSomething();" **

Edit : I was offered here to use DI framework like Guice, does this mean I will need to add the DI code in every entry point (i.e. "main" method) in all my projects, or there is a way to do it once for all projects?

like image 925
Gilad Baruchian Avatar asked Sep 06 '16 14:09

Gilad Baruchian


People also ask

Is it possible to delegate a method in Java 8?

It doesn't have an explicit delegate keyword as C#, but you can achieve similar in Java 8 by using a functional interface (i.e. any interface with exactly one method) and lambda:

What is delegation in object oriented programming?

In this article, we will learn the important object-oriented concept - Delegation. Delegation means hand over the responsibility for a particular task to another class or method.

What are the methods in Java?

Java provides some pre-defined methods, such as System.out.println (), but you can also create your own methods to perform certain actions: static means that the method belongs to the Main class and not an object of the Main class. You will learn more about objects and how to access methods through objects later in this tutorial.

What is delegation vs inheritance in Java?

Delegation vs Inheritance in Java. Inheritance in Java programming is the process by which one class takes the property of another other class. i.e. the new classes, known as derived or child class, take over the attributes and behavior of the pre-existing classes, which are referred to as base classes or super or parent class.


1 Answers

The classes using your data source should access it via an interface, and the correct instance provided to the class at construction time.

So first of all make DataSource an interface:

public interface DataSource {

    String getSomething();
}

Now a concrete 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
    }
}

Somewhere else 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 do the last step using a Dependency Injection framework like Spring or Guice if you want to get fancy.

Bonus points: In your unit tests you can provide a mock/stub implementation of DataSource instead and your client class will be none the wiser!

like image 144
Paolo Avatar answered Oct 12 '22 23:10

Paolo