我在Python中看到装饰器example:
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>";
}
}
如何使用像这样的Java Annotation这样的Python示例:
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
值传递给{{1} }}和BoldWrapper
因此它可以连接和如何返回它,因此ItalicWrapper
方法可以显示已连接的结果。
请告知我对注释的理解是否有问题。
答案 0 :(得分:3)
如果你对使用注释做这种东西特别感兴趣(你不必真的):
这个例子应该让你开始:
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>
}
}
答案 1 :(得分: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)但是注释也是一种选择。例如:
答案 2 :(得分:0)
这很晚了,但我认为这可能会对其他人有所帮助。从具有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>
答案 3 :(得分:0)
Python 装饰器很像 Java 注释,但原理却大不相同。
<块引用>注释,一种元数据形式,提供有关程序的数据,该数据不属于程序本身。注解对它们注解的代码的操作没有直接影响。
但是您可以使用字节码增强处理类文件。我做了一个简单的项目来实现这种方法。它在构建后使用 javassist
处理类文件。它在类中搜索具有指定注释的方法。并添加用于在包装方法和原始方法之间调用的桥接方法。看起来像是在调用 bridgeMethod() -> wrapperMethod() -> originalMethod()
。您可以参考https://github.com/eshizhan/funcwraps。
答案 4 :(得分:-1)
虽然这并没有解决如何使用注释的问题,而是使用&#34;装饰设计&#34;,我建议你使用&#34;构建器设计&#34;如果它更适合你的需要(似乎是这样)。
快速使用示例:
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