Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/340.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 面向对象编程:动态添加功能_Java_Oop - Fatal编程技术网

Java 面向对象编程:动态添加功能

Java 面向对象编程:动态添加功能,java,oop,Java,Oop,我正在寻找一种替代装饰图案的方法,使其更具活力。作为一个简单的例子,假设我们有以下代码: interface Resource { public String getName(); } interface Wrapper extends Resource { public Resource getSource(); } interface Readable extends Resource { public InputStream getInputStream();

我正在寻找一种替代装饰图案的方法,使其更具活力。作为一个简单的例子,假设我们有以下代码:

interface Resource {
    public String getName();
}

interface Wrapper extends Resource {
    public Resource getSource();
}

interface Readable extends Resource {
    public InputStream getInputStream();
}

interface Listable extends Resource {
    public List<Resource> getChildren();
}



class File implements Readable {
    ...
}

class Zip implements Listable, Wrapper {
    public Zip(Readable source) { ... }
}
我不希望(也不能)堆叠所有接口以相互扩展(例如,Listable extends Readable),也不能构造所有对象来实现所有功能,因为并非所有功能都相互关联,您希望能够通过包装来动态“装饰”对象

我相信这是一个常见的问题,但有没有一种模式可以解决它?当然,使用“包装器”接口,如果您愿意,您可以探测资源链以检查功能,但我不确定这是否是一种明智的方法

更新

问题是如上所述,并非所有的功能都是相关的,因此您无法构建一个良好的接口层次结构。例如,假设您具有以下任意新功能:

interface Rateable extends Resource {
    public int getRating();
}

class DatabaseRateable implements Rateable, Wrapper {
    public DatabaseRateable(Resource resource) { ... }
}
如果您运行:

Resource resource = new DatabaseRateable(new Zip(new File));
结果资源“丢失”了添加的所有功能(可读、可列出等)。 如果让应课差饷租值延长,说是应课差饷租值,那将是荒谬的


我可以再次递归地检查resource.getSource()并找出所有特性。在即时回复中,没有明确的解决方案,因此递归检查可能毕竟是一个不错的选择?

在我看来,这似乎是您在这里努力追求的概念,而java本身并没有这样做(请参阅我关于基于反射的java库的评论)。但是,在JVM上运行的其他语言肯定会这样做。例如-:


您可以在groovy中编写代码,使其与java代码的其余部分无缝配合,并在groovy中解决此问题。

在装饰对象时,通常只装饰对象的一个接口,以修改或添加其行为的一个方面。 可以使用不同的装饰器装饰对象的另一个接口。这些装饰师可以同时存在

您可以将一个装饰器传递给一个方法,将另一个传递给另一个方法

当您希望先用几个装饰器装饰对象,然后通过代码传递对象时,这会变得很麻烦

因此,对于您的情况,我建议您再次将decorators包装到一个对象中,该对象知道资源中存在哪种decorator

class Resource {
    private Readable readable; 
    private Listable listable;
    private Rateable rateable;

    setReadable(Readable readable) {
        this.readable = readable;
    }

    setListable(Listable listable) {
        this.listable = listable;
    }

    setRateable(Rateable rateable) {
        this.rateable = rateable;
    }

    public boolean isRateable(){
        return rateable != null;
    }

    public Rateable getRateable(){
        return rateable;
    }
    // etc
}

File file1 = new File();
Resource resource = new Resource(file1);
resource.setReadable(new ReadableFile(file1));
resource.setListable(new ListableFile(file1));
resource.setRateable(new DatabaseRateableFile(file1));
然后,您可以传递资源,其用户可以发现此特定资源具有哪些功能


允许您使用注释以更干净的方式执行此操作(以及更多操作)。你把碎片组合成复合材料。不过,这确实需要一些时间来适应。为资源滚动您自己的特定实现的优点是,它更容易向其他人解释。

我认为您正在寻找的是

链接的wikipedia页面有一个很好的支持它们的OOP语言列表。或者您是专门与Java联系在一起的?

也许

Readable r = zip.adapt( Readable.class );
这要求方法
adapt()
返回实现
Readable
接口的
zip
实例


这些实现通常使用一个“适配器管理器”,它知道如何为所有注册的类型构建包装器。

这里可能不太合适,但是动态功能发现:

public class Features {

    public <T> lookup(Class<T> intface) 
            throws UnsupportedOperationException {
        return lookup(intface, intface.getSimpleName());
    }

    public <T> lookup(Class<T> intface, String name) 
            throws UnsupportedOperationException {
        return map.get(...);
    }
}

public class X {
    public final Features FEATURES = new Features();
    ...
}

X x;
Readable r = x.FEATURES.lookup(Readable.class);
公共类功能{
公共查找(类接口)
抛出不支持的操作异常{
返回查找(intface,intface.getSimpleName());
}
公共查找(类接口、字符串名称)
抛出不支持的操作异常{
返回地图。获取(…);
}
}
公共X类{
公共最终功能=新功能();
...
}
X;
可读r=x.FEATURES.lookup(Readable.class);

我将提供我自己的建议(如原始问题中所述)作为答案。如果有足够多的人认为这是一个有价值的解决方案,或者没有更好的解决方案,我会接受它

简言之,我自己的解决方案包括使用包装器接口向后遍历资源,找出存在哪些特性。举个例子:

Resource resource = new DatabaseRateable(new Zip(new File));
你可以想象这样做:

public Readable asReadable(Resource resource) {
    if (resource instanceof Readable)
        return (Readable) resource;
    else if (resource instanceof Wrapper)
        return (asReadable( ((Wrapper) resource).getSource() );
    else
        return null;
}

您装饰这些对象的目的是什么?为什么
Zip
不能同时实现
可读性
?您能提供一个具体的例子说明这是一个问题吗?@Dai示例在update@flup向不知道这些特性是否存在的对象动态添加特性。运行时混合(与编译时相反)可以提供一个解决方案,但是我非常依赖java。java有一个mixin实现,请参阅。它从碎片构造复合物。不过,就您的目的而言,它可能是一个有点重的解决方案。@flup如果我正确理解了框架,那么Qi4j就不是“动态”的,因为必须编译组合等。但是,这些功能完全是动态的,不需要重新构建即可正常工作。@user1109519确实如此!(假设我对你的理解正确)请看。“对象的组成可能会随着时间的推移而改变。”问题是初始对象没有实现这些特性。这些特性被添加(它们本身也可以被装饰)。decorator模式假定您只是覆盖现有方法,而不是动态添加它们。如果不完全是这样,您也可以使用decorator添加行为。是的,但是如果您添加行为,则生成的decorator仍将实现现有行为的所有方法,此时它将变得不可行。问题确实是我想要传递一个装饰对象,你不需要实现装饰器中的所有其他方法。生成的对象将具有什么类型?你会经常用同样的方式装饰对象吗?如果你想使用装饰过的对象访问上述方法,你会这样做。生成的对象主要是一种资源,在需要时会对其进行特定功能的探测。在所有可能的组合中都有无数的特性
Resource resource = new DatabaseRateable(new Zip(new File));
public Readable asReadable(Resource resource) {
    if (resource instanceof Readable)
        return (Readable) resource;
    else if (resource instanceof Wrapper)
        return (asReadable( ((Wrapper) resource).getSource() );
    else
        return null;
}