实现一个同样功能可以有各种方法,功能简单时需要考虑的只有效率和可读性,功能复杂时就需要额外考虑扩展性。在设计程序时,使用合适的设计模式,不仅可以解决扩展性问题,还可以让程序结构更符合人类的思维直觉,富有艺术感。
这里介绍并实现了装饰器模式。
装饰器模式的说明是:动态地将责任(或功能)附加到对象上,若要扩展功能,装饰者提供了比继承更有弹性的替代方案。
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
来源:CSDN
作者:阔海星沉
链接:https://blog.csdn.net/ManWZD/article/details/104117292