19

我在 Python 中看到了装饰器示例:

def makebold(fn):
    def wrapped():
        return "<b>" + fn() + "</b>"
    return wrapped

def makeitalic(fn):
    def wrapped():
        return "<i>" + fn() + "</i>"
    return wrapped

@makebold
@makeitalic
def hello():
    return "hello world"

print hello() ## returns <b><i>hello world</i></b>

并且很好奇它是如何在 Java 中实现的,所以我搜索并获得了一些使用Decorator Design Pattern的示例。

public class Main {

    public static void main(String[] args) {
        Wrapper word = new BoldWrapper(new ItalicWrapper());
        // display <b><i>hello world</i></b>
        System.out.println(word.make("Hello World"));
    }
}

public interface Wrapper {

    public String make(String str);

}

public class BoldWrapper implements Wrapper {

    private Wrapper wrapper;

    public BoldWrapper() {

    }

    public BoldWrapper(Wrapper wrapper) {
        this.wrapper = wrapper;
    }

    @Override
    public String make(String str) {
        if(wrapper != null) {
            str = wrapper.make(str);
        }

        return "<b>" + str + "</b>";
    }

}

public class ItalicWrapper implements Wrapper {

    private Wrapper wrapper;

    public ItalicWrapper() {

    }

    public ItalicWrapper(Wrapper wrapper) {
        this.wrapper = wrapper;
    }

    @Override
    public String make(String str) {
        if(wrapper != null) {
            str = wrapper.make(str);
        }

        return "<i>" + str + "</i>";
    }

}

如何使用像上面的 Python 示例一样使用这样的 Java 注释

public class Main {
    public static void main(String[] args) {
        @BoldWrapper
        @ItalicWrapper
        String str = "Hello World";
        // Display <b><i>Hello World</i></b>
    }
}

public @interface BoldWrapper {
    public void wrap() default "<b>" + str + "</b>";
}

public @interface ItalicWrapper {
    public void wrap() default "<i>" + str + "</i>";
}

当我尝试制作示例时遇到了一些问题,问题是我不知道如何将str值从main方法传递给BoldWrapperItalicWrapper所以它可以连接以及如何返回它,所以main方法可以显示结果已串联

请告知我对注释的理解是否有问题。

4

5 回答 5

5

如果您对使用注释做这种事情特别感兴趣(您不必真的这样做):

这个例子应该让你开始:

public class AnnotationTest
{
    @Target( ElementType.METHOD )
    @Retention( RetentionPolicy.RUNTIME )
    public static @interface TagWrapper
    {
        public String[] value() default {};
    }

    public static interface TextFragment
    {
        public String getText();
    }

    public static class TagWrapperProcessor
    {
        public static String getWrapperTextFragment( TextFragment fragment )
        {
            try
            {
                Method getText = fragment.getClass().getMethod( "getText" );
                TagWrapper tagWrapper = getText.getAnnotation( TagWrapper.class );
                String formatString = "<%s>%s</%s>";
                String result = ( String ) getText.invoke( fragment );
                for ( String tag : tagWrapper.value() )
                {
                    result = String.format( formatString, tag, result, tag );
                }
                return result;
            }
            catch ( Exception e )
            {
                throw new RuntimeException( e );
            }
        }
    }

    public static class BoldItalicFragment implements TextFragment
    {

        private String _text;

        public BoldItalicFragment( String text )
        {
            _text = text;
        }

        @Override
        @TagWrapper(
        {
            "b", "i"
        } )
        public String getText()
        {
            return _text;
        }

    }

    @Test
    public void testStuff()
    {
        System.out.println( TagWrapperProcessor.getWrapperTextFragment( new BoldItalicFragment( "Hello, World!" ) ) ); // prints: <i><b>Hello, World!</b></i>
    }
}
于 2012-08-22T03:23:49.490 回答
2

这已经晚了,但我认为它可能会帮助其他人。从带有 Function 接口的 Java 8 开始,我们可以编写类似于 python 装饰器的东西,如下所示:

Function<Function<String, String>, Function<String, String>> makebold = func -> input -> "<b>" + func.apply(input) + "</b>";
Function<Function<String, String>, Function<String, String>> makeitalic = func -> input -> "<i>" + func.apply(input) + "</i>";

Function<String, String> helloWorld = input -> "hello world";
        System.out.println(makebold.apply(makeitalic.apply(helloWorld)).apply("")); // <b><i>hello world</i></b>
于 2019-04-04T04:35:33.203 回答
1

1)您引用的链接是一个很好的链接 - 它对 Java 的“装饰器模式”很公平。当然,“设计模式”本身独立于任何特定的 OO 语言:

2)这是另一个很好的链接:

在 Java 中,装饰器模式的一个经典示例是 Java I/O Streams 实现。

FileReader       frdr = new FileReader(filename);
LineNumberReader lrdr = new LineNumberReader(frdr);

4)所以是的,“装饰者模式”是这个问题的一个很好的候选者。

就个人而言,我更喜欢这种解决方案:

   String myHtml = 
     new BoldText (
       new ItalicText (
         new HtmlText ("See spot run")));

5)但是注释也是一种选择。例如:

于 2012-08-22T03:00:34.593 回答
0

尽管这不能解决如何根据需要使用注释,而不是使用“装饰器设计”,但如果它更适合您的需求(看起来如此),我可以建议您使用“构建器设计”。

快速使用示例:

public class BuilderPatternExample {

    public static void main(String args[]) {

        //Creating object using Builder pattern in java
        Cake whiteCake = new Cake.Builder()
                                 .sugar(1)
                                 .butter(0.5)
                                 .eggs(2)
                                 .vanilla(2)
                                 .flour(1.5)
                                 .bakingPowder(0.75)
                                 .milk(0.5)
                                 .build();

        //Cake is ready to eat :)
        System.out.println(whiteCake);
    }
}

输出: 蛋糕{糖=0.75,黄油=0.5,鸡蛋=2,香草=2,面粉=1.5,发酵粉=0.0,牛奶=0.5,樱桃=0}

有关完整的实现和很好的解释,请查看 http://javarevisited.blogspot.mx/2012/06/builder-design-pattern-in-java-example.html

于 2014-03-30T00:24:23.113 回答
0

Python 装饰器非常喜欢 java 注释,但原理却大不相同。

注释是元数据的一种形式,提供有关程序的数据,这些数据不属于程序本身。注释对其注释的代码的操作没有直接影响。

但是您可以使用字节码增强处理类文件。我做了一个简单的项目来实现这种方法。它在构建后使用javassist处理类文件。它在类中搜索具有指定注释的方法。并在包装方法和原始方法之间添加桥接方法进行调用。看起来,调用bridgeMethod() -> wrapperMethod() -> originalMethod(). 您可以参考https://github.com/eshizhan/funcwraps

于 2021-01-22T12:24:20.490 回答