设计模式学习笔记——装饰(Decorator)模式

设计模式学习笔记——装饰(Decorator)模式

@(设计模式)[设计模式, 装饰模式, decorator]

基本介绍

装饰模式主要是通过委托机制,继承被装饰者的父类或者实现其接口,来做到不断的为被装饰者添加装饰。

java中的io包就是使用装饰者模式的很好的案例。

装饰案例

类图

装饰案例类图

实现代码

Display抽象类
package com.pc.decorator.example;

/**
 * 显示抽象类
 * Created by Switch on 2017-02-21.
 */
public abstract class Display {
    /**
     * 获取每行的字符数
     *
     * @return 每行的字符数
     */
    public abstract int getColumns();

    /**
     * 获取行数
     *
     * @return 行数
     */
    public abstract int getRows();

    /**
     * 获取指定行的文本
     *
     * @param row 行数
     * @return 文本
     */
    public abstract String getRowText(int row);

    /**
     * 全部显示
     */
    public final void show() {
        for (int i = 0; i < this.getRows(); i++) {
            System.out.println(getRowText(i));
        }
    }
}
StringDisplay类
package com.pc.decorator.example;

/**
 * 字符串显示类
 * Created by Switch on 2017-02-21.
 */
public class StringDisplay extends Display {
    /**
     * 带显示的字符串
     */
    private String string;

    /**
     * 构造方法,传入字符串
     *
     * @param string 字符串
     */
    public StringDisplay(String string) {
        this.string = string;
    }

    @Override
    public int getColumns() {
        return this.string.getBytes().length;
    }

    @Override
    public int getRows() {
        return 1;
    }

    @Override
    public String getRowText(int row) {
        if (row == 0) {
            return this.string;
        }
        return null;
    }
}
Border抽象类
package com.pc.decorator.example;

/**
 * 边框装饰抽象类
 * Created by Switch on 2017-02-21.
 */
public abstract class Border extends Display {
    /**
     * 待装饰的对象
     */
    protected Display display;

    /**
     * 构造方法,传入待装饰的显示类对象
     *
     * @param display 显示类对象
     */
    public Border(Display display) {
        this.display = display;
    }
}
SideBorder类
package com.pc.decorator.example;

/**
 * 侧面边框装饰类
 * Created by Switch on 2017-02-21.
 */
public class SideBorder extends Border {
    /**
     * 装饰字符
     */
    private char decorateChar;

    /**
     * 构造方法,传入待装饰的显示类对象
     *
     * @param display 显示类对象
     */
    public SideBorder(Display display, char decorateChar) {
        super(display);
        this.decorateChar = decorateChar;
    }

    @Override
    public int getColumns() {
        return this.display.getColumns() + 2;
    }

    @Override
    public int getRows() {
        return this.display.getRows();
    }

    @Override
    public String getRowText(int row) {
        // 在两边加上装饰字符
        return this.decorateChar + display.getRowText(row) + this.decorateChar;
    }
}
FullBorder类
package com.pc.decorator.example;

/**
 * 完全边框装饰类
 * Created by Switch on 2017-02-21.
 */
public class FullBorder extends Border {
    /**
     * 构造方法,传入待装饰的显示类对象
     *
     * @param display 显示类对象
     */
    public FullBorder(Display display) {
        super(display);
    }

    @Override
    public int getColumns() {
        return display.getColumns() + 2;
    }

    @Override
    public int getRows() {
        return display.getRows() + 2;
    }

    @Override
    public String getRowText(int row) {
        if (row == 0) { // 上边框
            return "+" + makeLine('-', display.getColumns()) + "+";
        } else if (row == display.getRows() + 1) {  // 下边框
            return "+" + makeLine('-', display.getColumns()) + "+";
        } else { // 内容
            return "|" + this.display.getRowText(row - 1) + "|";
        }
    }

    /**
     * 生成一个重复的count次的ch字符串
     *
     * @param c     字符
     * @param count 次数
     * @return 重复的count次的ch字符串
     */
    private String makeLine(char c, int count) {
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < count; i++) {
            builder.append(c);
        }
        return builder.toString();
    }
}
测试类
package com.pc.decorator.example.test;

import com.pc.decorator.example.Display;
import com.pc.decorator.example.FullBorder;
import com.pc.decorator.example.SideBorder;
import com.pc.decorator.example.StringDisplay;
import org.junit.Test;

/**
 * Display Tester.
 *
 * @author Switch
 * @version 1.0
 */
public class DisplayTest {
    /**
     * 测试装饰模式
     */
    @Test
    public void testDisplay() {
        Display display1 = new StringDisplay("Hello World!");
        Display display2 = new SideBorder(display1, '#');
        Display display3 = new FullBorder(display2);

        display1.show();
        display2.show();
        display3.show();

        System.out.println();

        Display display4 = new FullBorder(new SideBorder(new FullBorder(new StringDisplay("Hello")), '#'));
        display4.show();
    }
}
运行结果
Hello World!
#Hello World!#
+--------------+
|#Hello World!#|
+--------------+

+---------+
|#+-----+#|
|#|Hello|#|
|#+-----+#|
+---------+

装饰模式中的角色

Component

增加功能时的核心角色。Component角色只是定义了接口(API)。在案例中,由Display 类扮演此角色。

ConcreteComponent

该角色实现了Component角色所定义的接口(API) 。在案例中,由StringDisplay类扮演此角色。

Decorator(装饰物)

该角色具有与Component角色相同的接口(API)。在它内部保存了被装饰对象——Component角色。Decorator角色知道自己要装饰的对象。在案例中,由Border类扮演此角色。

ConcreteDecorator(具体的装饰物)

该角色是具体的Decorator角色。在案例中,由SideBorder类和FullBorder类扮演此角色。

类图

装饰模式类图

GitHub:DesignPatternStudy

——————参考《图解设计模式》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值