Decorator in Java
Solution 1
If you are particularly interested in doing this kind of stuff with annotations (you don't have to really):
This example should get you started:
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>
}
}
Solution 2
This is late but I think it may help the other people. From Java 8 with Function interface, we can write something close to python decorator like this:
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>
Solution 3
1) The link you cited is a good one - it does justice to the "Decorator Pattern" with respect to Java. "Design Patterns" themselves, of course, are independent of any particular OO language:
2) Here is another good link:
In Java, a classical example of the decorator pattern is the Java I/O Streams implementation.
FileReader frdr = new FileReader(filename);
LineNumberReader lrdr = new LineNumberReader(frdr);
4) So yes, the "decorator pattern" is a good candidate for this problem.
Personally, I would prefer this kind of solution:
String myHtml =
new BoldText (
new ItalicText (
new HtmlText ("See spot run")));
5) However annotations are also an option. For example:
Crazenezz
Updated on January 23, 2021Comments
-
Crazenezz over 3 years
I see about decorator example in 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>
And got some curious how it can be implement in Java, so I search and got some example using 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>"; } }
How do I make this like the Python example above using a Java Annotation like this one:
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>"; }
I got some problem when I tried to make the sample, the problem is I don't know how I can pass the
str
value from themain
method to theBoldWrapper
andItalicWrapper
so it can concatenate and how to return it, so themain
method can display the result that has been concatenate.Please advise if there is something wrong with my understanding of annotation.
-
Crazenezz about 10 yearsThank you so much for the information, using the Builder Pattern is the key to solve the problem. But still I want to research more if possible to using Annotation to solve the problem. And I also aware that using annotation has side effect for the memory.