我有一个接口,Resource
它应该包装一些东西并在包装的对象上公开一些操作。
我的第一种方法是编写以下内容,同时牢记策略模式。
interface Resource<T> {
ResourceState read();
void write(ResourceState);
}
abstract class AbstractResource<T> implements Resource<T> {
// This is where the Strategy comes in.
protected AbstractResource(ResourceStrategy<T> strat) {
// ...
}
// Both the read and write implementations delegate to the strategy.
}
class ExclusiveResource<T> extends AbstractResource<T> { ... }
class ShareableResource<T> extends AbstractResource<T> { ... }
上述两种实现在使用的锁定方案(常规锁或读写锁)方面有所不同。
还有一个ResourceManager
,一个实体负责管理这些事情。我对客户使用的想法是:
ResourceManager rm = ...
MyCustomObject o = ...
MyCustomReadWriteStrategy strat = ...
rm.newResourceFor(o, "id", strat);
这样,客户端将知道资源,但不必直接处理资源(因此是包私有类)。另外,我可以自己实现一些公共资源,比如套接字,而客户端只会要求它们(即,我必须编写一个SocketStrategy implements ResourceStrategy<Socket>
)。
ResourceManager rm = ...
rm.newSocketResource("id", host, port);
要访问资源,他会向经理请求处理程序。这是因为每个线程都有一些特定的访问权限,因此管理器会创建一个具有适当访问权限的处理程序。
// This is in the ResourceManager class.
public ResourceHandler getHandlerFor(String id) {
if (!canThreadUseThisResource(id)) throw ...;
if (isThreadReaderOnly()) {
return new ResourceReadHandler( ... );
} else {
return new ResourceWriteHandler( ... );
}
}
这就是问题所在。
这种方法对我来说似乎很干净,对用户来说似乎也很直观。但是,正如暗示的那样,管理器保留了从标识符到资源的映射。这将如何声明,经理将如何从地图中检索资源?
Map<String, Resource<?>> map;
// Can I go around without any specific cast? Not sure yet.
Resource<?> r = map.get(id);
// This could have an enum ResourceType, to check if thread has privileges
// for the specific type.
这种设计是否可以接受和/或遵循良好实践?
或者,我可以消除泛型,并拥有ExclusiveResource
并且ShareableResource
是抽象和公共的。
然后,这些类将由我和客户针对所需的每种类型的资源(、、...)进行FileResource extends ExclusiveResource
扩展SocketResource extends ExclusiveResource
。
这可能会消除对策略模式的需要,但会将我的更多包暴露给用户。
这些替代方案中哪一个是最正确的,或被广泛接受为良好做法?
编辑:经过一番思考,我想我可以从Resource
接口中删除泛型,因为这是造成麻烦的原因,并将其保留在AbstractResource
其子类中。后者仍然可以让我对所使用的策略进行编译时验证。
public <T> void newExclusiveResourceFor(
T obj, String id, ResourceStrategy<T> strat) {
ExclusiveResource<T> r = new ExclusiveResource<>(obj, strat);
map.put(id, r);
}
但是,遵循继承方式似乎更正确。