Useful decorators implemented using pure Java.
These decorators implement AOP in pure Java. No dependencies required.
See usage in tests directory.
Decorators can wrap any objects, but they can be cast only to interfaces.
E. g.:
// Loggable is a decorator and Identity is a class
Identity identity = Loggable.decorate(new Identity()); // WRONG
// ^ casting to class, not an interface.
// class LocalPictureStorage implements PictureStorage
PictureStorage storage = Cache.decorate(new LocalPictureStorage()); // OK
// ^ casting to interface.
It means that only methods declared in interfaces can be wrapped by decorators.
And it is good since it encourages you not to have methods uncovered with interfaces.
Interface object = Decorator.decorate(target, args);
object.method1(); // decorator will handle that
Cached decorator caches methods' calls to target. Works well
with immutable objects and arguments (they have constant hashCode).
import com.github.scfj.decorators.Cache;
// ...
UserApi userApi = Cache.decorate(new UsersFromDatabase("jdbc://..."));
// Retreives user from database, interacts with IO for the first time.
User firstUser = userApi.userById(1);
// ...
User user1 = userApi.userById(1); // No IO, user is stored in memory.
See tests here and here to learn more.
Robust decorator makes objects less fragile.
import com.github.scfj.decorators.Robust;
//...
Connection connection = Robust.decorate(new PoorConnection(resource), 3);
connection.readBytes(); // won't fail fast, it will try 3 times before throwing exception
Connection connection = Robust.decorate(new PoorConnection(resource), 3, 300);
connection.readBytes(); // try 3 times with 300 ms delay