I have the following class/interface hierarchy:
+ interface Resource
|-- + abstract class AbstractResource
| |-- + class ...
|
|-- + interface ConcurrentResource
|-- + abstract class AbstractConcurrentResource
|-- + class ...
Where:
public interface Resource {
/* Some methods here */
}
public interface ConcurrentResource extends Resource {
void acquireFor(AccessMode mode);
void release();
/* ... */
}
This sounds logical to me. A Resource
, by itself, may or may not have an implementation aware of concurrent access. Hence, acquisition and release should be enforced by a more specific kind of resource, ConcurrentResource
. At least, it made some sense to me, at the time.
The AbstractResource
and AbstractConcurrentResource
are very similar, and I'd rather avoid code duplication, but the latter provides the same instance variables as volatile
, because it already has concurrent access in mind.
I'm now implementing the resource manager, and it has to deal with resource acquisition and release, where applicable. Meaning, if the resource is not concurrent, the manager doesn't worry about it, otherwise it has to be aware of it.
This directly translates to a ResourceManager
and a ConcurrentResourceManager
, since the former keeps a Map<String, Resource>
whereas the latter needs a Map<String, ConcurrentResource>
, or a lot of casts.
Having two managers, means that other classes that need a resource manager will also have to be aware of the two distinct managers, forking more implementations.
I figured I could wipe ConcurrentResource
and have those methods move up to Resource
, but I don't really feel sure about this approach. Should a resource, by itself, offer the possibility of concurrent access in its interface, even though some of its implementations do not support concurrency?
I think that may be misleading.
How would you approach this scenario?