装饰者模式

装饰者模式,在不改变一个对象本身功能的基础上给对象增加额外的新行为。比如,我们到书店买书,在不改变书籍本身的基础上,赠送个书签,或者要个包装袋

 

装饰者模式(Decorator Pattern):在不改变原有对象的基础上,动态的给对象增加一些额外的职责。就给对象增加功能来说,装饰者模式比继承的方式更加灵活。装饰者模式是一种对象结构型模式

装饰者模式,无须定义子类动态给对象增加职责,用对象之间的关联关系取代类之间的继承关系

 

装饰者模式结构,需要4个角色,抽象构件、具体构件、抽象装饰类、具体装饰类

抽象构件(Component):具体构件和抽象装饰类的共同父类,声明了具体构件中实现的业务方法

具体构件(ConcreteComponent):抽象构件类的子类,定义具体构件对象

抽象装饰类(Decorator):抽象构件类的子类,作用是给具体构件增加功能,具体功能在其子类中实现

具体装饰类(ConcreteDecorator):抽象装饰类的子类,给构件添加新的功能

 

下面还是以买书为例,讲解装饰者模式

去书店买书,增加书签不要钱,增加一个书的包装袋,需额外加钱

定义抽象书籍类,在这里相当于抽象构件

package com.design.structural.decorator;

/**
 * 抽象书籍类
 */
public abstract class AbstractBook {

    //书名
    public abstract void bookName();

    //价格
    public abstract void bookPrice();
}

定义具体书籍红楼梦,售价60元,相当于具体构件

package com.design.structural.decorator;

public class TheDreamofRedMansionBook extends AbstractBook{

    @Override
    public void bookName() {
        System.out.println("红楼梦");
    }

    @Override
    public void bookPrice() {
        System.out.println("售价60元");
    }
}

定义抽象书籍装饰类,相当于抽象装饰类

package com.design.structural.decorator;

public class AbstractDecorator extends AbstractBook{

    private AbstractBook abstractBook;

    public AbstractDecorator(AbstractBook abstractBook){
        this.abstractBook = abstractBook;
    }

    @Override
    public void bookName() {
        this.abstractBook.bookName();
    }

    @Override
    public void bookPrice() {
        this.abstractBook.bookPrice();
    }
}

定义书签装饰类,相当于具体装饰类

package com.design.structural.decorator;

/**
 * 书签装饰类
 */
public class BookmarkDecorator extends AbstractDecorator{

    public BookmarkDecorator(AbstractBook abstractBook) {
        super(abstractBook);
    }

    @Override
    public void bookName() {
        super.bookName();
        System.out.println("增加一个书签");
    }

    @Override
    public void bookPrice() {
        super.bookPrice();
    }
}

定义包装袋装饰类,相当于具体装饰类

package com.design.structural.decorator;

/**
 * 包装袋装饰
 */
public class PackDecorator extends AbstractDecorator{

    public PackDecorator(AbstractBook abstractBook) {
        super(abstractBook);
    }

    @Override
    public void bookName() {
        super.bookName();
        System.out.println("增加一个包装袋");
    }

    @Override
    public void bookPrice() {
        super.bookPrice();
        System.out.println("增加2元钱");
    }
}

 

类图如下

 

测试调用

不要书签和包装袋

package com.design.structural.decorator;

public class TestMain {

    public static void main(String[] args) {
        AbstractBook abstractBook = new TheDreamofRedMansionBook();
        //abstractBook = new BookmarkDecorator(abstractBook);
        //abstractBook = new PackDecorator(abstractBook);

        abstractBook.bookName();
        abstractBook.bookPrice();
    }
}

要书签和包装袋

package com.design.structural.decorator;

public class TestMain {

    public static void main(String[] args) {
        AbstractBook abstractBook = new TheDreamofRedMansionBook();
        abstractBook = new BookmarkDecorator(abstractBook);
        abstractBook = new PackDecorator(abstractBook);

        abstractBook.bookName();
        abstractBook.bookPrice();
    }
}

 

 

扩展

透明装饰者模式与半透明装饰者模式

透明装饰者模式(Transparent):标准的装饰者模式就是透明装饰者模式。透明装饰者模式要求客户端完全针对抽象编程,且对象全部声明为抽象构件类型。可以对一个已装饰过的对象进行多次装饰,得到更为复杂、功能更强大的对象。实现透明装饰者模式时,需要具体装饰类的方法覆盖抽象装饰类的方法,比如上边代码中的 bookName() 方法和 bookPrice() 方法,除此之外,还可以调用其他方法,增加新的功能

 

半透明装饰者模式(Semi-Transparent):用具体装饰类型来定义装饰之后的对象,用抽象构件类型来定义具体构件类型。即相对于客户端来说,具体构件类型无须关心,是透明的,但具体装饰类型必须指定,它是不透明的

请看下边代码,示例半透明装饰者模式

抽象书籍装饰类,相当于抽象装饰类

package com.design.structural.decorator;

public class AbstractDecorator extends AbstractBook{

    private AbstractBook abstractBook;

    public AbstractDecorator(AbstractBook abstractBook){
        this.abstractBook = abstractBook;
    }

    @Override
    public void bookName() {
        this.abstractBook.bookName();
    }

    @Override
    public void bookPrice() {
        this.abstractBook.bookPrice();
    }
}

书签装饰类,相当于具体装饰类

package com.design.structural.decorator;

/**
 * 书签装饰类
 */
public class BookmarkDecorator extends AbstractDecorator{

    public BookmarkDecorator(AbstractBook abstractBook) {
        super(abstractBook);
    }

    @Override
    public void bookName() {
        super.bookName();
        System.out.println("增加一个书签");
    }

    @Override
    public void bookPrice() {
        super.bookPrice();
    }

    public void pencil(){
        System.out.println("赠送一个铅笔");
    }
}

书签装饰类,即具体装饰类,自行增加了 pencil() 方法,这个方法在其父类抽象书籍装饰类中是没有的,因此是不透明的。这种方式更加灵活,设计相对简单,但最大的缺点是同一个对象不能多次装饰,且客户端需要有区别地对待装饰之前的对象和装饰之后的对象

 

 

装饰者模式总结

优点:继承的有力补充、比继承灵活;符合开闭原则;

缺点:增加更多的代码,增加程序复杂性;多次装饰的对象,较为复杂,不易调试

适用场景:扩展一个类,或给一个类添加职责;动态给对象添加功能;不能采用继承方式扩展系统或继承方式不利于扩展和维护系统时,采用装饰者模式

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

悟世君子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值