爪哇语中的装饰器

2022-09-02 10:56:47

我在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中实现它感到好奇,所以我搜索并使用装饰器设计模式获得了一些示例。

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方法可以显示已经连接的结果

如果我对注释的理解有问题,请告知。


答案 1

如果你特别有兴趣用注释做这种事情(你不必真的):

此示例应帮助您入门:

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>
    }
}

答案 2

这已经很晚了,但我认为它可能会帮助其他人。从带有函数接口的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>