Skip to content

Instantly share code, notes, and snippets.

@Ahnfelt
Last active August 29, 2015 14:13
Show Gist options
  • Save Ahnfelt/6ef713db4d5fe0113144 to your computer and use it in GitHub Desktop.
Save Ahnfelt/6ef713db4d5fe0113144 to your computer and use it in GitHub Desktop.
Frameworkless, minimal, typesafe Dependency Injection for Java.
interface ShopService {
void buy();
void sell();
}
interface DatabaseService {
void beginTransaction();
void commit();
void abort();
}
interface ShopLocator { ShopService shop(); }
interface DatabaseLocator { DatabaseService database(); }
class MyShopService<S extends DatabaseLocator> implements ShopService {
private final S services;
public MyShopService(S services) {
this.services = services;
}
@Override
public void buy() {
services.database().beginTransaction();
services.database().commit();
}
@Override
public void sell() {
services.database().beginTransaction();
services.database().commit();
}
}
class MyDatabaseService implements DatabaseService {
@Override public void beginTransaction() {}
@Override public void commit() {}
@Override public void abort() {}
}
// The class MyLocator is only mentioned somewhere in your Main file.
class MyLocator implements ShopLocator, DatabaseLocator {
private DatabaseService database = new MyDatabaseService();
private ShopService shop = new MyShopService<>(this);
@Override
public DatabaseService database() {
return database;
}
@Override
public ShopService shop() {
return shop;
}
}
@Ahnfelt
Copy link
Author

Ahnfelt commented Jan 14, 2015

  • Service interfaces like ShopService/DatabaseService define the services types of your system.
  • Locator interfaces like ShopLocator/DatabaseLocator define methods that locate a particular type of service.
  • The MyShopService example shows how to depend on a DatabaseService. The MyShopService type is generic in the type parameter S, which must extend DatabaseLocator, eg. it must be able to provide a DatabaseService.
  • The MyShopService constructor takes an argument of the S type and saves it. From then on, the services field can be used to locate the services that S extends locators for.
  • If MyShopService also needed to depend on SomeService, simply add it to the bound on S, eg. S extends DatabaseLocator & SomeLocator.
  • The MyLocator class is just an example that provides a value of type ? extends ShopLocator & DatabaseLocator, eg. suitable as the constructor argument of MyShopService.
  • The ShopService shop = new MyShopService<>(this); hides the type parameter S, which is really only useful inside the implementation of MyShopService anyway.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment