装饰模式又名包装(Wrapper)模式。可以用来代替继承对类功能进行扩展。
装饰模式中有以下角色:
抽象构件(Component)角色:给出一个抽象接口,以规范准备接收附加责任的对象。即要被装饰的对象的基本构成。
具体构件(ConcreteComponent)角色:定义一个将要接收附加功能的类
装饰角色(Decorator):持有一个构件(Component)对象的实例,并定义一个与抽象构件接口一致的接口
具体装饰角色(ConcreteDecorator):负责给构件对象“贴上”附加的功能
下面通过对船ship进行升级来描述。
代码
//抽象构件
public interface ship{
public void Cando();
}
//具体构件
class trueShip implements ship{
@Override
public void Cando() {
System.out.println("跑");
}
}
//装饰器--->装饰角色
class decorate implements ship{
protected ship sh;
public decorate(ship sh) {
this.sh=sh;
}
@Override
public void Cando() {
sh.Cando();
}
}
具体装饰角色
class warship extends decorate{
public warship(ship sh) {
super(sh);
// TODO Auto-generated constructor stub
}
public void fire() {
System.out.println("开炮");
}
@Override
public void Cando() {
super.Cando();
fire();
}
}
class AircraftCarrier extends decorate{
public AircraftCarrier(ship sh) {
super(sh);
// TODO Auto-generated constructor stub
}
public void jet() {
System.out.println("有飞机");
}
@Override
public void Cando() {
super.Cando();
jet();
}
}
测试
package cn.strugglenow.decorator;
public class client2 {
public static void main(String[] args) {
System.out.println("----------普通船---------");
trueShip ship = new trueShip();
ship.Cando();
System.out.println("----------普通军舰---------");
warship wship=new warship(ship);
wship.Cando();
System.out.println("----------航空母舰---------");
AircraftCarrier airShip =new AircraftCarrier(wship);
airShip.Cando();
}
}
装饰过程
我们首先有一个普通船作为具体构件。当我们调用warship wship=new warship(ship);进行装饰时,系统调用warship类的构造方法。
public warship(ship sh) {
super(sh);
// TODO Auto-generated constructor stub
}
由于worship类继承自decorate类,所以最后会调用decorate类的构造方法,即具体构件被传递给了decorate类,然后被其赋给了变量sh。然后调用Cando方法时,又是一层一层地向上,又调用到了sh.Cando()进而调用到具体构件ship的Cando()。外加上warship类自己的fire方法。此时worship类不仅可以调用自己的fire方法,还可以有具体构件的方法。就完成了装饰。AircraftCarrierl类也一样。