软件构造课学习体悟(四)关于装饰者模式(Decorator)

我们都知道在程序编写与实现中,可复用性是十分必要且对未来的编码大有裨益的。而面向复用的编程当然不能仅仅满足于单个类本身,Java语言的装饰者模式(Decorator)即是一种面向复用的结构型设计模式,主要强调的是多个类/对象之间的关系和交互过程。

一、
装饰模式的设计理念主要是以对客户端透明的方式动态扩展对象的功能,是继承关系的一个替代(继承会产生大量的子类,而且代码有冗余)。装饰模式可以在不创造更多子类的情况下,将对象的功能加以扩展。装饰模式把客户端的调用委派到被装饰类。装饰模式的关键在于这种扩展完全是透明的(装饰模式的透明性要求客户端程序不应该将对象声明为具体构件类型或具体装饰类型,而应该全部声明为抽象构件类型)。

二、
对于现实中的一些对象,我们经常将其经过抽象得到一个共性的父类接口,接口中含有这些对象的共性方法。如果想实现一个具体的对象,就来实现一个具体的子类,将其特有的方法加入,但是这样一来就出现了一个十分麻烦的问题。有一些子类的特点十分相近,比如说:对于球类运动而言,判定胜负的方法不同,比如足球可能会出现平局,而篮球则不会,因此两者的判定胜负的方法必然会存在不同,但是对于球员存在号码这点属性上却又是统一的,如果有对号码进行判断的方法,则两者可以相同。诸如此类的重复使得如果对于多个相近的实体对象想要分别实现则会出现大量的代码冗余重复。
装饰者模式就为编码者提供了这样一种设计模式来消除这种问题。它的主要思路是:对于每一个接口所对应的实体类中可能出现的特性进行子类的构造,然后通过委派机制,将这些特性的子类如同装饰物一般加到所需要实现的对象上。Decorator在编译实现的过程中体现了递归的思路。

三、
在这个模式中,共出现了以下几种角色:
Component(接口):它定义共有的属性和方法,通常不使用该接口,而是调用其实现类;
ConcreteComponent(起始对象):是接口的子类,它实现了对应的方法,也是装饰物所要装饰的类;
Decorator(装饰抽象类):是所有装饰类的基类,里面包含一个成员变量component,指向了其所要装饰的对象,它的主要作用就是把客户端的调用委派到被装饰类(注意:Decorator也可实现为接口,视期望的抽象程度而定);
ConcreteDecorator(具体装饰类):是具体的装饰类,既是Decorator的子类也是Component的子类,只要是待实现对象的一种特性就可以作为一个具体装饰类。

四、
下举一例来体现。
需求:定义animal接口并实现dog的具体类。
Component:

interface Animal{
void eat();//觅食
void breathe();//呼吸
void sleep();//睡觉
void sound();//叫声
}

ConcreteComponent:

public class ConcreteAnimal implements Animal{
@Override
public void eat(){...}
@Override
public void breathe(){...}
@Override
public void sleep(){...}
@Override
public void sound(){
System.out.println("Here is the voice of the animal\n");
}
}

Decorator:

public abstract class AnimalDecorator implements Animal{
protected final Animal animal;
public AnimalDecorator(Animal animal){
this.animal = animal;
}//委派
@Override
public void eat(){
animal.eat();
}
@Override
public void breathe(){
animal.breathe();
}
@Override
public void sleep(){
animal.sleep();
}
@Override
public void sound(){
animal.sound();
}
}

ConcreteDecorator:

public class ConcreteBark extends AnimalDecorator{
public ConcreteAD(Animal animal){
super(animal);
}
@Override
public void eat(){
super.eat();
}
@Override
public void breathe(){
super.breathe();
}
@Override
public void sleep(){
super.sleep();
}
@Override
public void sound(){
super.sound();
this.bark();
}
private void bark(){
System.out.println("Woof!");
}
}

客户端测试:

public class Test{
public static void main(String[] args){
Animal animal = new ConcreteAnimal();
animal.sound();
Animal dog = new ConcreteBark(animal);
dog.sound();
}

前者的结果只有一行字,后者在一行字后还加上了“Woof”。

以上是对于所学的Decorator模式的回顾以及举例。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值