我有一个接口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);
}
但是,遵循继承方式似乎更正确。
参考方案
正如dkaustubh和Paul Bellora所建议的那样,在Resource
接口中没有通用的合理理由。起初,我完全没有注意到这一点,因为我希望实现是通用的,所以我认为接口也应该是通用的。事实并非如此。
我在这里还有两个选择。
使用泛型
我应该在界面中删除通用名称。然后,我将得出以下结论。
interface Resource {
ResourceState read();
void write(ResourceState);
void dispose();
}
abstract class AbstractResource<T> implements Resource {
/* This is where the Strategy comes in.
* The generic ensures compile-time verification of the
* strategy's type. */
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> { ... }
// This is the behaviour the client implements, for custom resources.
public abstract class ResourceStrategy<T> {
public abstract ResourceState read(T obj);
public abstract void write(ResourceState state);
public abstract void dispose(T obj);
}
对客户端来说,只有ResourceHandler
,ResourceManager
,ResourceState
和ResourceStrategy
才需要公开。
使用继承
使用继承,我可以取得相同的结果,但需要权衡取舍。
public interface Resource {
ResourceState read();
void write(ResourceState);
void dispose();
}
/* These implement only the locking schemes. */
abstract class ExclusiveResource implements Resource { ... }
abstract class ShareableResource implements Resource { ... }
/* The user extends these for custom content and behaviour. */
public abstract class CustomExclusiveResource
extends ExclusiveResource { ... }
public abstract class CustomShareableResource
extends ShareableResource { ... }
资源现在对客户公开。
结论
Resource
不公开,使用泛型,客户端也需要了解策略。有了继承,它们就消失了,并将public
状态分配给资源。 例如:小文件可以完全读取到内存,而大文件可能需要适当大小的缓冲区。
除非缺少其他内容,否则可能只是选择问题,并考虑所需的API和用例。
Java中的<<或>>>是什么意思? - javaThis question already has answers here: Closed 7 years ago. Possible Duplicate: What does >> and >>> mean in Java?我在一些Java代码中遇到了一些陌生的符号,尽管代码可以正确编译和运行,但对于括号在此代码中的作用却感…
菱形运算符<>是否等于<?> - java我在util.TreeSet类中发现,其中一个构造函数正在使用具有空泛型类型的新TreeMap调用另一个构造函数。 public TreeSet(Comparator<? super E> comparator) { this(new TreeMap<>(comparator)); } new TreeMap<>是什么意思…
与哪些运算符>>兼容 - java我这里没有什么代码int b=3; b=b >> 1; System.out.println(b); 它可以完美工作,但是当我将变量b更改为byte,short,float,double时,它包含错误,但是对于变量int和long来说,它可以完美工作,为什么它不能与其他变量一起工作? 参考方案 位移位运算符(例如>>)与任何整数类型兼…
休眠映射<键,设置<值>> - java我有以下表格:@Entity @Table(name = "events") Event --id --name @Entity @Table(name = "state") State --id --name @Entity @Table(name = "action") Action --id …
Java中的“ <<”运算符 - java最喜欢的语句来自Java的Character类:(1 << Character.PARAGRAPH_SEPARATOR)) >> type PARAGRAPH_SEPARATOR是字节,type是整数。这句话中的操作员,他们做什么?如何以及在哪里可以使用这些运算符?这是oracles java.lang.Character文档。该类中…