Java Reference
In-Depth Information
On the other hand, the
Runner
class is especially designed to be easily extensible for
our needs.
This appendix gives a brief introduction to how to extend the
JU
nit
API
with
custom
Runner
objects. It also describes how to extend the Hamcrest
API
with cus-
tom matchers so that we eventually customize not only our runners but also our
assert calls.
B.1
Introducing the Interceptor pattern
So far in the topic, we've gotten to know a lot of design patterns: the Controller, the
Façade, Inversion of Control, and so on. Now it's time to look at another one: the
Interceptor pattern.
Design patterns in action: Interceptor
The Interceptor pattern can be described as a method that intercepts a business
method invocation. The pattern usually consists of several objects. The first one is
an
Interceptor
interface that defines one or more methods that your interceptors
will implement. The next is a
Delegate
object that holds a list of interceptors. The
Delegate
object is called at the intercepting points of your application, and it
invokes the interceptors one after another.
Here are some interesting features of the Interceptor pattern:
■
It propagates extensibility and flexibility.
■
It enables separation of concerns.
■
It increases reusability.
■
If not used properly, security issues might occur.
Imagine you're designing an application for a group of developers. You want them to
plug their code into your application as painlessly as possible, and at the same time
you don't want them to change it. What can you do? You can provide some points in
your application where the developers can intercept the invocation of the program
and introduce their own logic. Others don't need to change your code; they can sim-
ply plug their code into your framework.
B.2
Implementing a custom runner
Let's start implementing our own custom runner. As you might have already
guessed, we want to develop a custom runner that implements the Interceptor pat-
tern we just discussed.
We want to define an
Interceptor
interface, which will be implemented by the
various interceptors that we have. That's why we start with the
Interceptor
interface,
shown in listing B.1.