2012-08-22 79 views
12

我在Python看到装饰example装饰在Java中

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值传递给BoldWrapperItalicWrapper,所以它可以连接如何返回它,所以main方法可以显示已连接的结果

请指教我对注释的理解是否有问题。

+2

不,你不会是能够与注解做到这一点。 –

+0

有没有另一种方法使用java而不使用装饰器设计模式? – Crazenezz

+0

你可以用Java做对象修饰,但不能用注释。 –

回答

1

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

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)不过注释也是一种选择。例如:

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> 
    } 
} 
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,vanila = 2,面粉= 1.5,发粉= 0.0,牛奶= 0.5,樱桃= 0}

对于全面落实和很好的解释,请 http://javarevisited.blogspot.mx/2012/06/builder-design-pattern-in-java-example.html

+0

非常感谢您提供的信息,使用Builder模式是解决问题的关键。但是如果可能使用Annotation来解决这个问题,我仍然想研究更多。而且我也意识到使用注释对内存有副作用。 – Crazenezz