Decorator Pattern (padrão de desenho)/Exercício 1: Textos Formatados

From Wiki**3

Problema

Um texto é constituído por palavras. Quando o texto é apresentado, através do método render, cada palavra pode aparecer sem qualquer modificação de aspecto (utiliza-se o método render correspondente). É ainda possível modificar dinamicamente o aspecto das palavras, permitindo que sejam apresentadas em negrito, itálico, sublinhado, ou em combinações variadas (e.g. negrito e itálico ou itálico sublinhado, etc.). No entanto, a apresentação é sempre realizada da mesma forma (sempre através do método render).

Além de apresentável graficamente, um texto pode ser convertido numa cadeia de caracteres, contendo a sua informação textual (String). Esta operação é realizada através do método text (invocado sobre cada um dos elementos designados acima).

Implemente as classes que permitem representar o texto completo, as palavras, respectivas modificações gráficas. Implemente ainda uma aplicação que ilustre o comportamento. Represente as características gráficas da seguinte forma:

  • normal <span>normal</span>
  • negrito <b>negrito</b>
  • itálico <i>itálico</i>
  • sublinhado <u>sublinhado</u>

Solução

A solução apresentada abaixo não contempla o método text. Deixa-se como exercício para o leitor.

Diagrama UML

Este diagrama corresponde às classes abaixo definidas. Note-se queo método render está declarado em todas as classes. Não foi representado em algumas por simplicidade.

Diagrama de classes

Interface TextItem

Esta interface representa um item textual genérico, formatado ou não.

'Ficheiro TextItem.java'
public interface TextItem {
    /**
     * Text items can be rendered.
     *
     * @return rendered text item.
     */
    String render();
}

Class TextSpan

A text span contains some text.

'Ficheiro TextSpan.java'
public class TextSpan implements TextItem {

    /** The text in this span. */
    private String _text;

    /**
     * @param text
     *            the text in this span.
     */
    public TextSpan(String text) {
        _text = text;
    }

    /**
     * @see TextItem#render()
     */
    @Override
    public String render() {
        return "<span>" + _text + "</span>";
    }

}

Class TextFormat

The abstract format (root class for other formatting items). A text format may be applied to any text item.

'Ficheiro TextFormat.java'
public abstract class TextFormat implements TextItem {

    /** The text item to format. */
    private TextItem _textItem;

    /**
     * @param textItem
     *            the text item to format.
     */
    public TextFormat(TextItem textItem) {
        _textItem = textItem;
    }

    /**
     * @return the text item.
     */
    public TextItem getTextItem() {
        return _textItem;
    }

    /**
     * Subclasses will do the rest.
     *
     * @see TextItem#render()
     */
    public String render() {
        return _textItem.render();
    }

}

Class Bold

Bold format.

'Ficheiro Bold.java'
public class Bold extends TextFormat {

    /**
     * @param textItem the text item to format.
     */
    public Bold(TextItem textItem) {
        super(textItem);
    }

    /**
     * @see TextItem#render()
     */
    @Override
    public String render() {
        return "<b>" + super.render() + "</b>";
    }

}

Class Italic

Italic format.

'Ficheiro Italic.java'
public class Italic extends TextFormat {

    /**
     * @param textItem the text item to format.
     */
    public Italic(TextItem textItem) {
        super(textItem);
    }

    /**
     * @see TextItem#render()
     */
    @Override
    public String render() {
        return "<i>" + super.render() + "</i>";
    }

}

Class Underline

Underline format.

'Ficheiro Underline.java'
public class Underline extends TextFormat {

    /**
     * @param textItem the text item to format.
     */
    public Underline(TextItem textItem) {
        super(textItem);
    }

    /**
     * @see TextItem#render()
     */
    @Override
    public String render() {
        return "<u>" + super.render() + "</u>";
    }

}

Class App

Simple demo application.

'Ficheiro App.java'
public class App {

    /**
     * @param args
     */
    public static void main(String[] args) {
        TextItem span1 = new TextSpan("BATATA");
        TextItem text1 = new Bold(new Italic(span1));
        System.out.println(text1.render());
        
        TextItem span2 = new TextSpan("CEBOLA");
        TextItem text2 = new Underline(new Bold(new Italic(span2)));
        System.out.println(text2.render());
    }

}

Compiling and Running