Java 对象层次结构的工厂(多态静态方法解决方案) 让我们考虑下面的简化资源< /代码>层次结构: public abstract class Resource { static public boolean accepts(String resource); } public class AudioResource extends Resource { static public boolean accepts(String resource) { //Check if we can proceed this resource as audio //Some complex logic there ... } } public class VideoResource extends Resource { static public boolean accepts(String resource) { //Check if we can proceed this resource as video //Another complex logic there } }
Java 对象层次结构的工厂(多态静态方法解决方案) 让我们考虑下面的简化资源< /代码>层次结构: public abstract class Resource { static public boolean accepts(String resource); } public class AudioResource extends Resource { static public boolean accepts(String resource) { //Check if we can proceed this resource as audio //Some complex logic there ... } } public class VideoResource extends Resource { static public boolean accepts(String resource) { //Check if we can proceed this resource as video //Another complex logic there } },java,design-patterns,Java,Design Patterns,Resource有几十个子类,而且数量还在增长。每个次级资源: 有一些逻辑来确定它是否接受资源。例如,它可以用regexp或其他东西解析资源URL 不是设计上的独生子女 现在,我们想要创建一个工厂,它遍历所有可用的子类,并创建一个接受资源的工厂(使用accepts方法检查它) 类似这样(让我们假设Java有静态方法多态性): 公共类资源工厂{ 私有静态列表注册表; { //开始时填充注册表一次 } 公共静态资源createResource(字符串资源){ for(类类别:注册表){ if(分
Resource
有几十个子类,而且数量还在增长。每个次级资源:
- 有一些逻辑来确定它是否接受资源。例如,它可以用regexp或其他东西解析资源URL李>
- 不是设计上的独生子女李>
accepts
方法检查它)
类似这样(让我们假设Java有静态方法多态性):
公共类资源工厂{
私有静态列表注册表;
{
//开始时填充注册表一次
}
公共静态资源createResource(字符串资源){
for(类类别:注册表){
if(分类接受(资源))
返回clazz.createInstance(资源);
}
}
}
不幸的是(或者不是?),Java不支持多态静态方法考虑到这一点,设计资源
和资源工厂
的可能方法是什么?您可以使用:
public interface Resource {
// some methods
}
public interface ResourceFactory {
boolean acceptsResource(String resource);
Resource createResource(String resource) throws UnsupportedResourceException;
}
public final MultiResourceFactory implements ResourceFactory{
private static final ServiceLoader<ResourceFactory > resourceFactoryLoader
= ServiceLoader.load(ResourceFactory .class);
private static final MultiResourceFactory INSTANCE;
private MultiResourceFactory(){
}
public static MultiResourceFactory getInstance(){
if (INSTANCE == null){
INSTANCE = new MultiResourceFactory();
}
return INSTANCE;
}
@Override
public boolean acceptsResource(String resource){
for (ResourceFactory resourceFactory : resourceFactoryLoader) {
if (resourceFactory.acceptsResource(resource)){
return true;
}
}
return false;
}
@Override
public Resource createResource(String resource) throws UnsupportedResourceException{
for (ResourceFactory resourceFactory : resourceFactoryLoader) {
if (resourceFactory.acceptsResource(resource)){
return resourceFactory.createResource(resource);
}
}
throw new UnsupportedResourceException(resource);
}
公共接口资源{
//一些方法
}
公共接口资源工厂{
布尔值acceptsResource(字符串资源);
资源createResource(字符串资源)引发UnsupportedResourceException;
}
公共最终MultiResourceFactory实现ResourceFactory{
私有静态最终服务加载程序resourceFactoryLoader
=ServiceLoader.load(ResourceFactory.class);
私有静态最终多资源工厂实例;
私有多资源工厂(){
}
公共静态MultiResourceFactory getInstance(){
if(实例==null){
实例=新的MultiResourceFactory();
}
返回实例;
}
@凌驾
公共布尔值acceptsResource(字符串资源){
对于(ResourceFactory ResourceFactory:resourceFactoryLoader){
if(resourceFactory.acceptsResource(资源)){
返回true;
}
}
返回false;
}
@凌驾
公共资源createResource(字符串资源)引发UnsupportedResourceException{
对于(ResourceFactory ResourceFactory:resourceFactoryLoader){
if(resourceFactory.acceptsResource(资源)){
返回resourceFactory.createResource(资源);
}
}
抛出新的UnsupportedResourceException(资源);
}
有关如何注册工厂的信息,请参阅ServiceLoader:
注意:代码未经测试另一种方法是使用反射。
如何接受
可以是非静态的?在这种情况下,我们需要在每次需要检查时创建实例。您可以在其他位置创建实例,并将它们作为构造函数参数传递到调用方类代码中。反射肯定是一种方法,但我们没有重新定义在这种情况下,每个资源
都需要一个接口。编写资源
时根本不需要接受。从本质上说,它们变成了单例,但按惯例,而不是单例模式。这称为依赖项注入。感谢您的回答!因此,我们对每个资源
强制执行一个工厂。我考虑过这一点虽然考虑到ServiceLoader
的文档几乎描述了我需要的东西…可能,这是目前最好的解决方案。顺便说一句,你知道一些其他可能的设计方法吗?没有很多附加对象?(我指的是每个资源
增加一个ResourceFactory
)。
public interface Resource {
// some methods
}
public interface ResourceFactory {
boolean acceptsResource(String resource);
Resource createResource(String resource) throws UnsupportedResourceException;
}
public final MultiResourceFactory implements ResourceFactory{
private static final ServiceLoader<ResourceFactory > resourceFactoryLoader
= ServiceLoader.load(ResourceFactory .class);
private static final MultiResourceFactory INSTANCE;
private MultiResourceFactory(){
}
public static MultiResourceFactory getInstance(){
if (INSTANCE == null){
INSTANCE = new MultiResourceFactory();
}
return INSTANCE;
}
@Override
public boolean acceptsResource(String resource){
for (ResourceFactory resourceFactory : resourceFactoryLoader) {
if (resourceFactory.acceptsResource(resource)){
return true;
}
}
return false;
}
@Override
public Resource createResource(String resource) throws UnsupportedResourceException{
for (ResourceFactory resourceFactory : resourceFactoryLoader) {
if (resourceFactory.acceptsResource(resource)){
return resourceFactory.createResource(resource);
}
}
throw new UnsupportedResourceException(resource);
}