DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
  1. DZone
  2. Data Engineering
  3. Data
  4. Singletons Must Die

Singletons Must Die

The Singleton pattern has gone from being a pattern to an anti-pattern in recent years. With this being the case, how can we define things globally without using the Singleton pattern?

Yegor Bugayenko user avatar by
Yegor Bugayenko
·
Jun. 29, 16 · Opinion
Like (23)
Save
Tweet
Share
30.77K Views

Join the DZone community and get the full member experience.

Join For Free

I think it's too obvious to say that a singleton is an anti-pattern as there are tons of articles about that (singleton being an anti-pattern). However, more often than not, the question is how to define global things without a singleton; and the answer to that is not obvious for many of us. There are several examples: a database connection pool, a repository, a configuration map, etc. They all naturally seem to be "global"; but what do we do with them?

Perdita Durango (1997) by Álex de la Iglesia
Perdita Durango (1997) by Álex de la Iglesia

I assume you already know what a singleton is and why it's an anti-pattern. If not, I recommend you read this StackOverflow thread: What is so bad about singletons?

Now that we agree it's a bad deal, what do we do if we need to, let's say, have access to a database connection pool in many different places within the application? We simply need something like this:

class Database {
  public static Database INSTANCE = new Database();
  private Database() {
    // create a connection pool
  }
  public java.sql.Connection connect() {
    // Get new connection from the pool
    // and return
  }
}

Later in at, say, the JAX-RS REST method, we need to retrieve something from the database:

@Path("/")
class Index {
  @GET
  public String text() {
    java.sql.Connection connection =
      Database.INSTANCE.connect();
    return new JdbcSession(connection)
      .sql("SELECT text FROM table")
      .fetch(new SingleOutcome(String.class))
  }
}

In case you're not familiar with JAX-RS, it's a simple MVC architecture, and this text() method is a "controller". Additionally, I'm using SqlSession, a simple JDBC wrapper from jcabi-jdbc.

We need that Database.INSTANCE to be a singleton, right? We need it to be globally available so that any MVC controller can have direct access to it. Since we all understand and agree that a singleton is an evil thing, what do we replace it with?

A dependency injection is the answer.

We need to make this database connection pool dependency of the controller and ensure it's provided through a constructor. However, in this particular case, for JAX-RS, we can't do it through a constructor thanks to its ugly architecture. But we can create a ServletContextListener, instantiate a Database in its contextInitialized() method, and add that instance as an attribute of servletContext. Then, inside the controller, we retrieve the servlet context by adding the javax.ws.rs.core.Context annotation to a setter and using getAttribute() on it. This is absolutely terrible and procedural, but it's better than a singleton.

A proper object-oriented design would pass an instance of Database to all objects that may need it through their constructors.

Nonetheless, what do we do if there are many dependencies? Do we make a 10-argument constructor? No, we don't. If our objects really need 10 dependencies to do their work, we need to break them down into smaller ones.

That's it. Forget about singletons; never use them. Turn them into dependencies and pass them from object to object through the operator new.

Database connection Die (manufacturing)

Published at DZone with permission of Yegor Bugayenko. See the original article here.

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • Java Development Trends 2023
  • Beginners’ Guide to Run a Linux Server Securely
  • Why It Is Important To Have an Ownership as a DevOps Engineer
  • Spring Cloud: How To Deal With Microservice Configuration (Part 1)

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends: