4. The problem …
public class MediaPlayer {
private InputSource inputSource;
private OutputDevice outputDevice;
/**
* Class constructor.
*/
public MediaPlayer() {
inputSource = new FileInputSource(“c:/media/movie.avi”);
outputDevice = new Screen();
}
/**
* Play media.
*/
public void play() {
while (running) {
// Read from 'inputSource' and write to 'outputDevice'.
}
}
}
5. The problem …
/**
* Represents an input source.
*/
public interface InputSource {
// Business methods.
}
/**
* Represents an output device.
*/
public interface OutputDevice {
// Business methods.
}
6. The problem …
Media Player
<< InputSource >> <<TargetDevice>>
File (C:/….) Screen
7. The problem …
Configuration file
source =
C:/media/file.avi
Media Player
<< InputSource >> <<TargetDevice>>
File (<?>) Screen
8. The problem …
Configuration file
source =
C:/media/file.avi
targetClass =
example.ScreenTarget
Media Player
<< InputSource >> <<TargetDevice>>
File (<?>) <?>
9. The problem …
Configuration file
Database
Media Player
X
X
source =
C:/media/file.avi
targetClass =
example.ScreenTarget
<< InputSource >> <<TargetDevice>>
File (<?>) <?>
10. The problem …
Web service Configuration file
Database
Media Player
X
X
source =
C:/media/file.avi
targetClass =
example.ScreenTarget
<< InputSource >> <<TargetDevice>>
File (<?>) <?>
11. The problem …
Web service Configuration file
Database
Media Player
X
X
source =
C:/media/file.avi
targetClass =
example.ScreenTarget
<< InputSource >> << Target >>
File (<?>) <?>
12. The problem …
The problem with the design …
Driven by behavior and not by functionality
» Too strict, cannot be changed easily.
» Hard to extend
» Can barely be reused (if at all).
[1]
» Contradicts the ‘Open-Close principle’.
[1] Open/closed principle by Bertrand Meyer
13. The problem …
Media Player
<< InputSource >> << TargetDevice >>
File (C:/….) Screen
14. The problem …
<< InputSource >> << TargetDevice >>
Media Player
15. The problem …
/**
* Represents an input source.
*/
public interface InputSource {
// Business methods.
}
/**
* Represents an output device.
*/
public interface OutputDevice {
// Business methods.
}
16. The problem …
public class MediaPlayer {
private InputSource inputSource;
private OutputDevice outputDevice;
/**
* Class constructor.
*/
public MediaPlayer() {
inputSource = new FileInputSource(“c:/media/movie.avi”);
outputDevice = new Screen();
}
/**
* Play media.
*/
public void play() {
while (running) {
// Read from 'inputSource' and write to 'outputDevice'.
}
}
}
17. The problem …
public class MediaPlayer {
private InputSource inputSource;
private OutputDevice outputDevice;
public void setInputSource(InputSource inputSource) {
this.inputSource = inputSource;
}
public void setOutputDevice(OutputDevice outputDevice) {
this.outputDevice = outputDevice;
}
That’s our
/**
* Play media.
business logic.
*/
public void play() {
while (running) {
// Read from 'inputSource' and write to 'outputDevice'.
}
}
}
18. The problem …
What we’ve accomplished…
Design by functionality
» Concentrates on functionality only
No lookup or creation of resources,
Separation of concerns.
» We’re not limited to certain behavior
Source and Target can be anything,
Source and Target can be fetched from any where
• Configuration file, Database, Web service, …
19. The problem …
What we’ve accomplished… (continued)
» We can inject any source / target !
E.g.: deployable on other platforms
Quickly inject mockups
• Required for Agile development
• Required for unit testing.
21. Inversion of Control
» Is a conceptual abstraction in software development.
[1]
» Introduced by Martin Fowler’s in 1988.
» Has 3 flavors,
Constructor injection (Dependency injection)
Setter injection (Dependency injection)
Dependency lookup.
[1] Martin Fowler – Dependency injection
22. Inversion of Control
Constructor injection
» Inject required resources via constructor.
public class ConstructorInjection {
private final DataSource dataSource;
private final int timeout;
/**
* Class constructor.
*
* @param dataSource Database connection.
* @param timeout Query timeout.
*/
public ConstructorInjection(DataSource dataSource, int timeout) { ... }
}
23. Inversion of Control
Constructor injection
» Pros:
Require user to specify all required resources.
Object is guaranteed to be injected with resources.
• May cancel object if a resource is not fulfilled ( == null).
public ConstructorInjection(DataSource dataSource, int timeout) {
if (dataSource == null || timeout < 1)
throw new IllegalArgumentException();
this.dataSource = dataSource;
this.timeout = timeout;
}
24. Inversion of Control
Constructor injection
» Cons:
Sometimes tedious,
• Must inject all resources or replace them with null.
Does not work well for a large number of dependencies.
public BadConstructorInjection(DataSource dataSource,
int timeout, Dialect dialect, String characterSet, double threashold,
boolean eagerly, Formatter messageFormatter, ...) {
}
25. Inversion of Control
Setter injection
» Inject required resources via setXXX() method.
Using JavaBean™ mutators.
public class SetterInjection {
private DataSource dataSource;
private int timeout;
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
public void setTimeout(int timeout) {
this.timeout = timeout;
}
}
26. Inversion of Control
Setter injection
» Pros:
Inject as many dependencies as you want.
Each resource/value treated independently.
» Cons:
Debatable issues …
public void setTimeout(int timeout) {
if (timeout < 0) {
throw new IllegalArgumentException("Timeout cannot be negative.");
}
this.timeout = timeout;
}
27. Inversion of Control
Dependency lookup
» Split resource locating between user and
implementation.
» Used much less than Constructor/Setter injections.
public void lookupDS(JNDIContext context) throws NamingException {
dataSource = (DataSource) context.lookup("env:/ds/oracleDataSource");
}
public void locateConfigFile(File rootDir) throws NamingException {
// Search file system for configuration file, starting with ‘rootDir’.
}
29. Benefits
» Full separation of concerns
Reusable components
Extendable components.
» Design and development by functionality.
Each object/module is focused on its business logic.
Produce a better, small, more efficient code.
» Agility.
Excellent for Agile practices (e.g.: XP, TDD, …).