简体   繁体   中英

Singleton Pattern, Configuration and Dependency Injection

I am currently porting a C library to Java. The C library connects to an external device and provides functions to configure the device and receive data. The core of my design is a Connection class that encapsulates the connection to the device and provides the low-level C API mapping generated using JNA.

Since most of the C library doesn't translate that well into the OO-World of Java (Single header library containing 100+ functions) i have a couple of "Manager" classes that provide access to most of the functionality.

Creating more than one of these classes doesn't make sense, since the C library only manages one resource of everything (configuration, data-buffer, etc). So i want to implement the Singleton pattern for my Java classes (effectively also signaling the users of my new java library, that there is only ONE Manager object in the whole system).

Additionally i want to be able to configure these Manager classes using an external config file. I have never implemented a configuration utility before, so i don't really know where to put that.

Lastly ALL of my Manager classes need a reference to a Connection object.

So i need a design that allows me to:

  1. Make my Java classes unique (Singleton Pattern)
  2. Inject my Connection object
  3. Configure my classes using a config file

Any ideas?

For the first two points, something like this would do the trick :

public class Connection{

    private static Connection instance = null;
    private String connectionString;

    protected Connection() {
    }

    public static Connection getInstance() {
       if(instance == null) {
          instance = new Connection();
       }
       return instance;
    }

    public void setConnectionString(String connectionString){
        this.connectionString = connectionString;
    }

    public String getConnectionString(){
        return this.connectionString;
    }
}

It's a classic example of a singleton in java. The constructor is protected , so you can't use the new keyword to instantiate it. Instead, you use it like this :

Connection con = Connection.getInstance();

getInstance() takes care of the instantiation and ensures only one instance of your singleton will ever exist. For instance, this :

    Connection con = Connection.getInstance();
    con.setConnectionString("foobar");

    Connection con2 = Connection.getInstance();
    System.out.println(con2.getConnectionString());

will print foobar

For the third point, I would refer you to this question where it has already been answered.

public static Connection getInstance() {
       if(instance == null) {
          instance = new Connection();
       }
       return instance;
}

This implementation violates the singleton principle. Consider to use one of both lazy initialization methods:

  1. with the synchronized key word public synchronized static Connection getInstance() { ... }

  2. init-on-demand holder idiom.

     public final class Connection { private static class Holder { private static final Connection INSTANCE = new Connection(); } private Connection() {} public static Connection getInstance() { return Holder.INSTANCE; } } 

To that, the init on demand holder idiom is a lazy synchronized Singleton and more performant than the first solution with the synchronized key word.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM