Coding-21-装饰器模式

為{幸葍}努か 提交于 2020-01-30 20:17:19

  实现一个同样功能可以有各种方法,功能简单时需要考虑的只有效率和可读性,功能复杂时就需要额外考虑扩展性。在设计程序时,使用合适的设计模式,不仅可以解决扩展性问题,还可以让程序结构更符合人类的思维直觉,富有艺术感。
  这里介绍并实现了装饰器模式

  装饰器模式的说明是:动态地将责任(或功能)附加到对象上,若要扩展功能,装饰者提供了比继承更有弹性的替代方案。

  Attach additional responsibilities to an object dynamically keeping the same interface.Decorators provide a flexible alternative to subclassing for extending functionality.

Talk is cheap, show me code

  以 HTML 的渲染为例,对一段文本 “hello world” 进行渲染,例如加黑、加斜体。

  • Python 的装饰器
# 加黑装饰器
def renderbold(func):
    def wrapped():
        return "<b>" + func() + "</b>"
    return wrapped

# 加斜体装饰器
def renderitalic(func):
    def wrapped():
        return "<i>" + func() + "</i>"
    return wrapped

# 自下而上调用装饰器
@renderbold
@renderitalic
def helloworld():
    return "hello world"

print(helloworld()) 
## 返回 <b><i>hello world</i></b>
  • Java 实现装饰器
/* 基础抽象类 */
abstract class HtmlRender{
    // 抽象地方法
    public abstract String render();
}
/* 实体类,提供文本 */
class HelloWorldHtml extends HtmlRender{
    @Override
    public String render(){
        return "hello world";
    }
}
/* 装饰器抽象类,和实体类一样,继承了基础抽象类:装饰之后的对象的基础类型不变,只是多了一些责任 */
abstract class HtmlDecorator extends HtmlRender{
    private HtmlRender htmlrender = null;
    public HtmlDecorator(HtmlRender htmlrender){
        this.htmlrender = htmlrender;
    }
    @Override
    public String render(){
        return this.htmlrender.render();
    }
}
/* 装饰器实体类,加黑装饰器 */
class BoldDecorator extends HtmlDecorator{
    public BoldDecorator(HtmlRender htmlrender){
        super(htmlrender);
    }
    // 重写父类的方法
    public String render(){
        String str = super.render();
        return("<b>" + str + "</b>");
    }
}
/* 装饰器实体类,加斜体饰器 */
class ItalicDecorator extends HtmlDecorator{
    public ItalicDecorator(HtmlRender htmlrender){
        super(htmlrender);
    }
    // 重写父类的方法
    public String render(){
        String str = super.render();
        return("<i>" + str + "</i>");
    }
}
class DecoratorDemo{
    public static void main(String[] args){
        HtmlRender htmlrender = new HelloWorldHtml();
        // 第一次修饰,加斜体
        htmlrender = new ItalicDecorator(htmlrender);
        // 第二次修饰,加黑
        htmlrender = new BoldDecorator(htmlrender);
        // 渲染完毕
        System.out.println(htmlrender.render());
    }
}

// 输出结果 <b><i>hello world</i></b>
总结
  • Python 的装饰器是语法的一部分,由于函数也是对象,可以直接装饰函数,使用更直观(像一个真实的装饰品),但是定义装饰器函数语法不太直观,使用了闭包函数;
  • Java 的装饰器是一种面向对象的设计模式,使用了普通语法实现稍微复杂,且使用起来并且不太直观;
  • 一些简单基本的功能不建议使用装饰器,会影响可读性。
参考资料

https://www.cnblogs.com/volcano-liu/p/10897897.html
https://www.jianshu.com/p/ab702e4d4ba7

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!