I am developing an application where I would like to use the observer pattern in the following way:
I have 2 classes:
public abstract class Storage<V>{
private Set<V> values;
private String filename;
protected Storage(String filename) throws ClassNotFoundException, IOException {
values = new HashSet<>();
this.filename = filename;
load();
}
...
public boolean add(V v) throws IllegalArgumentException {
if (values.contains(v))
throw new IllegalArgumentException("L'elemento è già presente");
return values.add(v);
}
...
}
Repository which is a class for saving a collection of Objects. below is a subclass that implements the singleton pattern (the others are practically the same, only the specified generic type changes)
public class AccountStorage extends Storage<Account>{
private static AccountStorage instance = null;
private AccountStorage(String filename) throws ClassNotFoundException, IOException {
super(filename);
}
public static synchronized AccountStorage getInstance() throws ClassNotFoundException, IOException {
if (instance == null) {
String savefile = "accounts.ob";
instance = new AccountStorage(savefile);
}
return instance;
}
after which I have a controller class (Controller for Spring MVC) which through a post request receives an Account in JSON format, deserializes it and adds it to the collection (Tremite the AccountStorage class) like this:
#PostMapping(value = "new/user", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
#ResponseBody
public ResponseEntity<String> newAccount(#RequestBody Account a) {
synchronized (accounts) {
try {
accounts.add(a);
// accounts.save()
} catch (IllegalArgumentException e) {
return new ResponseEntity<String>(e.getMessage(), HttpStatus.BAD_REQUEST);
} catch (IOException e) {
return new ResponseEntity<String>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
}
}
}
where accounts is: AccountStorage accounts = AccountStorage.getInstance();
I would like to make sure that, after each addition (or other methods that modify the collection) it is saved to file without calling the function affixed each time after the modification.
My idea is to use the Observer pattern. But I don't know which class must be an Observer and which Observable (assuming this approach is the correct solution).
The common practice for implementing the Observer pattern is to define an Observer interface (Listener) which will declare a general contact and each observer-implementation should provide an action which would be triggered whenever an event occurs.
A subject maintains a collection of observers (listeners), and exposes methods which allow to add and remove (subscribe/unsubscribe) an observer. Event-related behavior resides in the subject, and when a new event happens, every subscribed observer (i.e. each observer that is currently present in the collection) will be notified.
An event to which we are going to listen to is a case when a new Account gets added into an AccountStorage. And AccountStorage would be a subject. That implies that AccountStorage should hold a reference to a collection of observers, provide a functionality to subscribe/unsubscribe and override method add() of the Storage class in order to trigger all the observers when a new account will be added.
Why can't we add a collection of observers and all related functionality into the Storage class so that every implementation will inherit it? It's a valid question, the answer is that in such a scenario we can't be specific in regard to the nature of the event because we even don't know its type - method add(V) expects a mysterious V. Hence, the observer interface and its method would be faceless. It was the downside of the standard interfaces Observer and Observable that are deprecated since JDK version 9. Their names as well as the method-name update() tell nothing about an event that would be observed. It's only slightly better than define an interface MyInterface with a method myMethod() - no clue where you can use it and what actions should follow when myMethod() is fired.
It's a good practice when names of observers are descriptive, so that it's clear without looking at the code what they are meant to do. And it's not only related to the Observer pattern, it is a general practice which is called a self-documenting code.
Let's start by defining an observer interface, I'll call it listener just because AccountAddedListener sounds a bit smoothly, and it's quite common to use the terms listener and observer interchangeably.
public interface AccountAddedListener {
void onAccountAdded(Account account);
}
Now let's proceed with an implementation of the observer, let's say we need a notification manager:
public class NotificationManager implements AccountAddedListener {
#Override
public void onAccountAdded(Account account) {
// send a notification message
}
}
Now it's time to turn the AccountStorage into a subject. It should maintain a reference collection of observers, Set is a good choice because it'll not allow to add the same observer twice (which would be pointless) and is able to add and remove elements in a constant time.
Whenever a new account gets added, subject iterates over the collection of observers and invokes onAccountAdded() method on each of them.
We need to define a method to add a new observer, and it's also good practice to add another one to be able to unregister the observer when it's no longer needed.
public class AccountStorage extends Storage<Account> {
private Set<AccountAddedListener> listeners = new HashSet<>(); // collection of observers
#Override
public boolean add(Account account) throws IllegalArgumentException {
listeners.forEach(listener -> listener.onAccountAdded(account)); // notifying observers
return super.add(account);
}
public boolean registerAccountAddedListener(AccountAddedListener listener) {
return listeners.add(listener);
}
public boolean unregisterAccountAddedListener(AccountAddedListener listener) {
return listeners.remove(listener);
}
// all other functionality of the AccountStorage
}
I don't have a GUI (my classes are part of a Minecraft Mod). I wanted to be able to mimic C# event framework: A class declares events and lets others subscribe to them.
My first approach was to create a class called EventArgs and then do something like this:
public class EventArgs
{
public boolean handled;
}
#FunctionalInterface
public interface IEventHandler<TEvtArgs extends EventArgs>
{
public void handle(Object source, TEvtArgs args);
}
public class Event<TEvtArgs extends EventArgs>
{
private final Object owner;
private final LinkedList<IEventHandler<TEvtArgs>> handlers = new LinkedList<>();
public Event(Object owner)
{
this.owner = owner;
}
public void subscribe(IEventHandler<TEvtArgs> handler)
{
handlers.add(handler);
}
public void unsubscribe(IEventHandler<TEvtArgs> handler)
{
while(handlers.remove(handler));
}
public void raise(TEvtArgs args)
{
for(IEventHandler<TEvtArgs> handler : handlers)
{
handler.handle(owner, args);
if(args.handled)
break;
}
}
}
Then a class would do something like this:
public class PropertyChangedEvtArgs extends EventArgs
{
public final Object oldValue;
public final Object newValue;
public PropertyChangedEvtArgs(final Object oldValue, final Object newValue)
{
this.oldValue = oldValue;
this.newValue = newValue;
}
}
public class SomeEventPublisher
{
private int property = 0;
private final Random rnd = new Random();
public final Event<PropertyChangedEvtArgs> PropertyChanged = new Event<>(this);
public void raiseEventOrNot(int value)
{
if(rnd.nextBoolean())//just to represent the fact that the event is not always raised
{
int old = property;
property = value;
PropertyChanged.raise(new PropertyChangedEvtArgs("old(" + old + ")", "new(" + value + ")"));
}
}
}
public class SomeSubscriber
{
private final SomeEventPublisher eventPublisher = new SomeEventPublisher();
public SomeSubscriber()
{
eventPublisher.PropertyChanged.subscribe(this::handlePropertyAChanges);
}
private void handlePropertyAChanges(Object source, PropertyChangedEvtArgs args)
{
System.out.println("old:" + args.oldValue);
System.out.println("new:" + args.newValue + "\n");
}
public void someMethod(int i)
{
eventPublisher.raiseEventOrNot(i);
}
}
public class Main
{
private static final SomeSubscriber subscriber = new SomeSubscriber();
public static void main(String[] args)
{
for(int i = 0; i < 10; ++i)
{
subscriber.someMethod(i);
}
}
}
The biggest problem with this naïve approach is that it breaks proper encapsullation by exposing raise as public. I can't see a way around it, and maybe my whole pattern is wrong. I would like some ideas.
There's also a related problem: I would like the events to be raised immediately after the method raising them returns. Is there a way to synchronize this using threads or some other construct? The caller code, of course, can't be involved in the task of synchronization. It has to be completely transparent to it.
The best thing to do here is to avoid implementing your own event framework in the first place, and instead rely on some existing library. Out of the box Java provides EventListener, and at a minimum you can follow the patterns documented there. Even for non-GUI applications most of this advice applies.
Going beyond the JDK Guava provides several possible options, depending on your exact use case.
The most likely candidate is EventBus, which:
allows publish-subscribe-style communication between components without requiring the components to explicitly register with one another (and thus be aware of each other).
Or ListenableFuture (and ListeningExecutorService) which:
allows you to register callbacks to be executed once [a task submitted to an Executor] is complete, or if the computation is already complete, immediately. This simple addition makes it possible to efficiently support many operations that the basic Future interface cannot support.
Or the Service API which:
represents an object with an operational state, with methods to start and stop. For example, webservers, RPC servers, and timers can implement the Service interface. Managing the state of services like these, which require proper startup and shutdown management, can be nontrivial, especially if multiple threads or scheduling is involved.
This API similarly lets you register listeners to respond to state changes in your services.
Even if none of these options directly work for your use case, take a look at Guava's source code for examples of event-driven behavior and listeners you can try to emulate.
The book Growing Object Oriented Software gives several examples in jMock where the state is made explicit without exposing it through an API. I really like this idea. Is there a way to do this in Mockito?
Here's one example from the book
public class SniperLauncherTest {
private final States auctionState = context.states("auction state")
.startsAs("not joined");
#Test public void addsNewSniperToCollectorAndThenJoinsAuction() {
final String itemId = "item 123";
context.checking(new Expectations() {{
allowing(auctionHouse).auctionFor(itemId); will(returnValue(auction));
oneOf(sniperCollector).addSniper(with(sniperForItem(item)));
when(auctionState.is("not joined"));
oneOf(auction).addAuctionEventListener(with(sniperForItem(itemId)));
when(auctionState.is("not joined"));
one(auction).join(); then(auctionState.is("joined"));
}});
launcher.joinAuction(itemId);
}
}
I used a spy for the self same exercise:
http://docs.mockito.googlecode.com/hg/latest/org/mockito/Mockito.html#13
I changed my SniperListener mock into a spy thus:
private final SniperListener sniperListenerSpy = spy(new SniperListenerStub());
private final AuctionSniper sniper = new AuctionSniper(auction, sniperListenerSpy);
And also created a stubbed implementation of SniperListener:
private class SniperListenerStub implements SniperListener {
#Override
public void sniperLost() {
}
#Override
public void sniperBidding() {
sniperState = SniperState.bidding;
}
#Override
public void sniperWinning() {
}
}
The book uses JMock's "States", but I used a nested enum instead:
private SniperState sniperState = SniperState.idle;
private enum SniperState {
idle, winning, bidding
}
You then have to use regular JUnit asserts to test for the state:
#Test
public void reportsLostIfAuctionClosesWhenBidding() {
sniper.currentPrice(123, 45, PriceSource.FromOtherBidder);
sniper.auctionClosed();
verify(sniperListenerSpy, atLeastOnce()).sniperLost();
assertEquals(SniperState.bidding, sniperState);
}
Not that I'm aware of. I've used mockito a far amount and there's nothing in the doco similar to what I read on the JMock site about states. If I have it correctly they basically limit the time at which an exepection can occur to the duration of a specific state of another object. It's an interesting idea, but I'm struggling to see the applications for it.
In Mockito you can execute code using Stubbing with callbacks to do the same job. In the callback method you can execute further validations of the state. Alternatively you can employ a Custom argument matcher as they are also executed at the time of the call.
Both of these give you access to the code at execution time which is the time you want to check the state.
When applying this pattern Delegation Event Model, is it correct to put ALL the code in the fire... methods and pass the parameters from the public method?
Like this
public void addBananas(Banana banana) {
fireBananaAdded(banana);
}
private void fireBananaAdded(Banana banana) {
//Create event etc and add banana to list here
}
Or should I have the add to list part in this example in the addBananas method instead? Because if I do it this way I will not have the opportunity to "attach" the banana object to the event-object which will be passed to the listeners, right?
I would put as much logic in addBanana() that is related to actually adding the Banana as I can.
When I'm done with addBanana(), I would call fireBananaAdded() which would generate the appropriate BananaAddedEvent and send it to the BananaAddedListeners (or just BananaListeners, which ever you have.)
To put the ADD logic in the FIRE method is simply, well, BANANAS!
public void addBananas(Banana banana) {
if(BananaHolder.hasRoom()) {
BananaHolder.add(banana);
fireBananaAdded(banana);
}
}
private void fireBananaAdded(Banana banana) {
BananaAddedEvent event = new BananaAddedEvent(banana);
for(BananaListener listener : listenersByType(Banana.class)) {
listener.bananaAdded(event);
}
}
let's say we have a CountryList object in our application that should return the list of countries. The loading of countries is a heavy operation, so the list should be cached.
Additional requirements:
CountryList should be thread-safe
CountryList should load lazy (only on demand)
CountryList should support the invalidation of the cache
CountryList should be optimized considering that the cache will be invalidated very rarely
I came up with the following solution:
public class CountryList {
private static final Object ONE = new Integer(1);
// MapMaker is from Google Collections Library
private Map<Object, List<String>> cache = new MapMaker()
.initialCapacity(1)
.makeComputingMap(
new Function<Object, List<String>>() {
#Override
public List<String> apply(Object from) {
return loadCountryList();
}
});
private List<String> loadCountryList() {
// HEAVY OPERATION TO LOAD DATA
}
public List<String> list() {
return cache.get(ONE);
}
public void invalidateCache() {
cache.remove(ONE);
}
}
What do you think about it? Do you see something bad about it? Is there other way to do it? How can i make it better? Should i look for totally another solution in this cases?
Thanks.
google collections actually supplies just the thing for just this sort of thing: Supplier
Your code would be something like:
private Supplier<List<String>> supplier = new Supplier<List<String>>(){
public List<String> get(){
return loadCountryList();
}
};
// volatile reference so that changes are published correctly see invalidate()
private volatile Supplier<List<String>> memorized = Suppliers.memoize(supplier);
public List<String> list(){
return memorized.get();
}
public void invalidate(){
memorized = Suppliers.memoize(supplier);
}
Thanks you all guys, especially to user "gid" who gave the idea.
My target was to optimize the performance for the get() operation considering the invalidate() operation will be called very rare.
I wrote a testing class that starts 16 threads, each calling get()-Operation one million times. With this class I profiled some implementation on my 2-core maschine.
Testing results
Implementation Time
no synchronisation 0,6 sec
normal synchronisation 7,5 sec
with MapMaker 26,3 sec
with Suppliers.memoize 8,2 sec
with optimized memoize 1,5 sec
1) "No synchronisation" is not thread-safe, but gives us the best performance that we can compare to.
#Override
public List<String> list() {
if (cache == null) {
cache = loadCountryList();
}
return cache;
}
#Override
public void invalidateCache() {
cache = null;
}
2) "Normal synchronisation" - pretty good performace, standard no-brainer implementation
#Override
public synchronized List<String> list() {
if (cache == null) {
cache = loadCountryList();
}
return cache;
}
#Override
public synchronized void invalidateCache() {
cache = null;
}
3) "with MapMaker" - very poor performance.
See my question at the top for the code.
4) "with Suppliers.memoize" - good performance. But as the performance the same "Normal synchronisation" we need to optimize it or just use the "Normal synchronisation".
See the answer of the user "gid" for code.
5) "with optimized memoize" - the performnce comparable to "no sync"-implementation, but thread-safe one. This is the one we need.
The cache-class itself:
(The Supplier interfaces used here is from Google Collections Library and it has just one method get(). see http://google-collections.googlecode.com/svn/trunk/javadoc/com/google/common/base/Supplier.html)
public class LazyCache<T> implements Supplier<T> {
private final Supplier<T> supplier;
private volatile Supplier<T> cache;
public LazyCache(Supplier<T> supplier) {
this.supplier = supplier;
reset();
}
private void reset() {
cache = new MemoizingSupplier<T>(supplier);
}
#Override
public T get() {
return cache.get();
}
public void invalidate() {
reset();
}
private static class MemoizingSupplier<T> implements Supplier<T> {
final Supplier<T> delegate;
volatile T value;
MemoizingSupplier(Supplier<T> delegate) {
this.delegate = delegate;
}
#Override
public T get() {
if (value == null) {
synchronized (this) {
if (value == null) {
value = delegate.get();
}
}
}
return value;
}
}
}
Example use:
public class BetterMemoizeCountryList implements ICountryList {
LazyCache<List<String>> cache = new LazyCache<List<String>>(new Supplier<List<String>>(){
#Override
public List<String> get() {
return loadCountryList();
}
});
#Override
public List<String> list(){
return cache.get();
}
#Override
public void invalidateCache(){
cache.invalidate();
}
private List<String> loadCountryList() {
// this should normally load a full list from the database,
// but just for this instance we mock it with:
return Arrays.asList("Germany", "Russia", "China");
}
}
Whenever I need to cache something, I like to use the Proxy pattern.
Doing it with this pattern offers separation of concerns. Your original
object can be concerned with lazy loading. Your proxy (or guardian) object
can be responsible for validation of the cache.
In detail:
Define an object CountryList class which is thread-safe, preferably using synchronization blocks or other semaphore locks.
Extract this class's interface into a CountryQueryable interface.
Define another object, CountryListProxy, that implements the CountryQueryable.
Only allow the CountryListProxy to be instantiated, and only allow it to be referenced
through its interface.
From here, you can insert your cache invalidation strategy into the proxy object. Save the time of the last load, and upon the next request to see the data, compare the current time to the cache time. Define a tolerance level, where, if too much time has passed, the data is reloaded.
As far as Lazy Load, refer here.
Now for some good down-home sample code:
public interface CountryQueryable {
public void operationA();
public String operationB();
}
public class CountryList implements CountryQueryable {
private boolean loaded;
public CountryList() {
loaded = false;
}
//This particular operation might be able to function without
//the extra loading.
#Override
public void operationA() {
//Do whatever.
}
//This operation may need to load the extra stuff.
#Override
public String operationB() {
if (!loaded) {
load();
loaded = true;
}
//Do whatever.
return whatever;
}
private void load() {
//Do the loading of the Lazy load here.
}
}
public class CountryListProxy implements CountryQueryable {
//In accordance with the Proxy pattern, we hide the target
//instance inside of our Proxy instance.
private CountryQueryable actualList;
//Keep track of the lazy time we cached.
private long lastCached;
//Define a tolerance time, 2000 milliseconds, before refreshing
//the cache.
private static final long TOLERANCE = 2000L;
public CountryListProxy() {
//You might even retrieve this object from a Registry.
actualList = new CountryList();
//Initialize it to something stupid.
lastCached = Long.MIN_VALUE;
}
#Override
public synchronized void operationA() {
if ((System.getCurrentTimeMillis() - lastCached) > TOLERANCE) {
//Refresh the cache.
lastCached = System.getCurrentTimeMillis();
} else {
//Cache is okay.
}
}
#Override
public synchronized String operationB() {
if ((System.getCurrentTimeMillis() - lastCached) > TOLERANCE) {
//Refresh the cache.
lastCached = System.getCurrentTimeMillis();
} else {
//Cache is okay.
}
return whatever;
}
}
public class Client {
public static void main(String[] args) {
CountryQueryable queryable = new CountryListProxy();
//Do your thing.
}
}
Your needs seem pretty simple here. The use of MapMaker makes the implementation more complicated than it has to be. The whole double-checked locking idiom is tricky to get right, and only works on 1.5+. And to be honest, it's breaking one of the most important rules of programming:
Premature optimization is the root of
all evil.
The double-checked locking idiom tries to avoid the cost of synchronization in the case where the cache is already loaded. But is that overhead really causing problems? Is it worth the cost of more complex code? I say assume it is not until profiling tells you otherwise.
Here's a very simple solution that requires no 3rd party code (ignoring the JCIP annotation). It does make the assumption that an empty list means the cache hasn't been loaded yet. It also prevents the contents of the country list from escaping to client code that could potentially modify the returned list. If this is not a concern for you, you could remove the call to Collections.unmodifiedList().
public class CountryList {
#GuardedBy("cache")
private final List<String> cache = new ArrayList<String>();
private List<String> loadCountryList() {
// HEAVY OPERATION TO LOAD DATA
}
public List<String> list() {
synchronized (cache) {
if( cache.isEmpty() ) {
cache.addAll(loadCountryList());
}
return Collections.unmodifiableList(cache);
}
}
public void invalidateCache() {
synchronized (cache) {
cache.clear();
}
}
}
I'm not sure what the map is for. When I need a lazy, cached object, I usually do it like this:
public class CountryList
{
private static List<Country> countryList;
public static synchronized List<Country> get()
{
if (countryList==null)
countryList=load();
return countryList;
}
private static List<Country> load()
{
... whatever ...
}
public static synchronized void forget()
{
countryList=null;
}
}
I think this is similar to what you're doing but a little simpler. If you have a need for the map and the ONE that you've simplified away for the question, okay.
If you want it thread-safe, you should synchronize the get and the forget.
What do you think about it? Do you see something bad about it?
Bleah - you are using a complex data structure, MapMaker, with several features (map access, concurrency-friendly access, deferred construction of values, etc) because of a single feature you are after (deferred creation of a single construction-expensive object).
While reusing code is a good goal, this approach adds additional overhead and complexity. In addition, it misleads future maintainers when they see a map data structure there into thinking that there's a map of keys/values in there when there is really only 1 thing (list of countries). Simplicity, readability, and clarity are key to future maintainability.
Is there other way to do it? How can i make it better? Should i look for totally another solution in this cases?
Seems like you are after lazy-loading. Look at solutions to other SO lazy-loading questions. For example, this one covers the classic double-check approach (make sure you are using Java 1.5 or later):
How to solve the "Double-Checked Locking is Broken" Declaration in Java?
Rather than just simply repeat the solution code here, I think it is useful to read the discussion about lazy loading via double-check there to grow your knowledge base. (sorry if that comes off as pompous - just trying teach to fish rather than feed blah blah blah ...)
There is a library out there (from atlassian) - one of the util classes called LazyReference. LazyReference is a reference to an object that can be lazily created (on first get). it is guarenteed thread safe, and the init is also guarenteed to only occur once - if two threads calls get() at the same time, one thread will compute, the other thread will block wait.
see a sample code:
final LazyReference<MyObject> ref = new LazyReference() {
protected MyObject create() throws Exception {
// Do some useful object construction here
return new MyObject();
}
};
//thread1
MyObject myObject = ref.get();
//thread2
MyObject myObject = ref.get();
This looks ok to me (I assume MapMaker is from google collections?) Ideally you wouldn't need to use a Map because you don't really have keys but as the implementation is hidden from any callers I don't see this as a big deal.
This is way to simple to use the ComputingMap stuff. You only need a dead simple implementation where all methods are synchronized, and you should be fine. This will obviously block the first thread hitting it (getting it), and any other thread hitting it while the first thread loads the cache (and the same again if anyone calls the invalidateCache thing - where you also should decide whether the invalidateCache should load the cache anew, or just null it out, letting the first attempt at getting it again block), but then all threads should go through nicely.
Use the Initialization on demand holder idiom
public class CountryList {
private CountryList() {}
private static class CountryListHolder {
static final List<Country> INSTANCE = new List<Country>();
}
public static List<Country> getInstance() {
return CountryListHolder.INSTANCE;
}
...
}
Follow up to Mike's solution above. My comment didn't format as expected... :(
Watch out for synchronization issues in operationB, especially since load() is slow:
public String operationB() {
if (!loaded) {
load();
loaded = true;
}
//Do whatever.
return whatever;
}
You could fix it this way:
public String operationB() {
synchronized(loaded) {
if (!loaded) {
load();
loaded = true;
}
}
//Do whatever.
return whatever;
}
Make sure you ALWAYS synchronize on every access to the loaded variable.