设计模式学习总结(七)--装饰者模式

定义

装饰者模式又叫包装(Wrapper)模式。装饰者模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案。

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

在装饰模式中的角色:

  • 抽象构件(Component)角色:给出一个抽象接口,以规范准备接收附加责任的对象。
  • 具体构件(ConcreteComponent)角色:定义一个将要接收附加责任的类。
  • 装饰(Decorator)角色:持有一个构件(Component)对象的实例,并定义一个与抽象构件接口一致的接口。
  • 具体装饰(ConcreteDecorator)角色:负责给构件对象“贴上”附加的责任。

优缺点

优点:

  • 相比继承关系提供更多的灵活性
  • 通过使用不同的具体装饰类以及这些装饰类的排列组合,设计师可以创造出很多不同行为的组合。

缺点:

  • 类数量容易爆炸
  • 会使系统变复杂

实例

需求:

小明要买一个山东煎饼,煎饼里面可以填充很多东西,如香肠、油条、里脊,小明每天加的料都不同。请根据以上条件做一个价格计算程序。

添加一个饼接口:

/**
 * 饼接口
 */
public interface IPancake {

    String getDesc();

    BigDecimal getPrice();
}

实现一个山东煎饼:

/**
 * 山东煎饼
 */
public class ShandongPancake implements IPancake {

    @Override
    public String getDesc() {
        return "山东煎饼";
    }

    @Override
    public BigDecimal getPrice() {
        return new BigDecimal(4);
    }
}

添加一个饼配料接口:

/**
 * 饼配料接口
 */
public interface ICakeIngredients extends  IPancake{

}

实现饼配料:

public class Egg implements ICakeIngredients {
    private IPancake pancake;

    public Egg(IPancake pancake){
        this.pancake = pancake;
    }

    @Override
    public String getDesc() {
        return  pancake.getDesc() +" + 鸡蛋";
    }

    @Override
    public BigDecimal getPrice() {
        return pancake.getPrice().add(new BigDecimal(1));
    }
}

public class Sausage implements ICakeIngredients {
    private IPancake pancake;

    public Sausage(IPancake pancake){
        this.pancake = pancake;
    }

    @Override
    public String getDesc() {
        return  pancake.getDesc() +" + 香肠";
    }

    @Override
    public BigDecimal getPrice() {
        return pancake.getPrice().add(new BigDecimal(1.5));
    }
}

public class Fritters implements ICakeIngredients {
    private IPancake pancake;

    public Fritters(IPancake pancake){
        this.pancake = pancake;
    }

    @Override
    public String getDesc() {
        return  pancake.getDesc() +" + 油条";
    }

    @Override
    public BigDecimal getPrice() {
        return pancake.getPrice().add(new BigDecimal(2));
    }
}

接下来我们来模拟下购买场景:

    public static void main(String[] args) {
        // 普通山东煎饼
        IPancake ordinaryShandongPancake = new ShandongPancake();
        System.out.println(String.format("%s ¥%s", ordinaryShandongPancake.getDesc(),
                ordinaryShandongPancake.getPrice()));

        // 加料山东煎饼
        IPancake feedingShandongPancake = new ShandongPancake();
        // 加一个鸡蛋
        feedingShandongPancake = new Egg(feedingShandongPancake);
        // 加一个香肠
        feedingShandongPancake = new Sausage(feedingShandongPancake);
        // 加一个油条
        feedingShandongPancake = new Fritters(feedingShandongPancake);
        // 再加一个鸡蛋
        feedingShandongPancake = new Egg(feedingShandongPancake);

        System.out.println(String.format("%s ¥%s", feedingShandongPancake.getDesc(),
                feedingShandongPancake.getPrice()));
    }

控制台输出:

山东煎饼 ¥4
山东煎饼 + 鸡蛋 + 香肠 + 油条 + 鸡蛋 ¥9.5

原文地址:https://www.cnblogs.com/markLogZhu/p/11460449.html

时间: 2024-08-03 09:09:03

设计模式学习总结(七)--装饰者模式的相关文章

设计模式学习笔记之装饰者模式

装饰者模式     动态的将责任附加到对象上.若要扩展功能,装饰者模式提供了比继承更有弹性的替代方案. 说明: 1.装饰者和被装饰者对象有相同的超类型: 2.可以用一个或者多个装饰者包装一个对象: 3.既然装饰者和被装饰者对象有相同的超类型,所以在任何需要原始对象(被装饰者)的场合,可以用装饰过的对象代替它: 4.装饰者可以在委托被装饰者的行为之前 与 / 或 之后,加上自己的行为,以达到特定的目的: 5.对象可以在任何时候被装饰,所以可以在运行时动态地.不限量地用你喜欢的装饰者来装饰对象. 在

《Head First 设计模式》学习笔记——观察者模式 + 装饰者模式

装饰者模式是JDK中另一个使用较多的设计模式,上一个是观察者模式(在Swing中大量使用),业内好的API设计无一离不开常见的设计模式,通常我们所说要阅读源码,也是为了学习大牛们的设计思路.----题记 设计模式 观察者模式:定义了对象之间一对多的依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会受到通知并自动更新. 装饰者模式:动态地将责任附加到对象上.若要扩展功能,装饰者提供比继承者更有弹性的替代方案. 设计原则 (1)封装变化. (2)多用组合,少用继承. (3)针对接口编程,而不是

设计模式(八)装饰器模式Decorator(结构型)

设计模式(八)装饰器模式Decorator(结构型) 1. 概述 若你从事过面向对象开发,实现给一个类或对象增加行为,使用继承机制,这是所有面向对象语言的一个基本特性.如果已经存在的一个类缺少某些方法,或者须要给方法添加更多的功能(魅力),你也许会仅仅继承这个类来产生一个新类—这建立在额外的代码上. 通过继承一个现有类可以使得子类在拥有自身方法的同时还拥有父类的方法.但是这种方法是静态的,用户不能控制增加行为的方式和时机.如果  你希望改变一个已经初始化的对象的行为,你怎么办?或者,你希望继承许

Java设计模式(四) 装饰器模式 代理器模式

(七)装饰器模式 Decorator 装饰器模式是为了动态的给一个对象增加一些新功能.装饰对象与被装饰的对象需要实现同一个接口,装饰对象持有被装饰对象的实例. interface DecoratorSourceable{ public void method(); } //被装饰类 class DecoratorSource implements DecoratorSourceable{ public void method(){ System.out.println("Source"

Java设计模式(三)-装饰者模式

我们都知道,可以使用两种方式给一个类或者对象添加行为. 一是使用继承.继承是给一个类添加行为的比较有效的途径.通过使用继承,可以使得子类在拥有自身方法的同时,还可以拥有父类的方法.但是使用继承是静态的,在编译的时候就已经决定了子类的行为,我们不便于控制增加行为的方式和时机. 二是使用关联.组合即将一个对象嵌入到另一个对象中,由另一个对象来决定是否引用该对象来扩展自己的行为.这是一种动态的方式,我们可以在应用程序中动态的控制. 与继承相比,关联关系的优势就在于不会破坏类的封装性,且具有较好的松耦合

PHP设计模式学习笔记: 责任链模式(Chain of Responsibility)

// 抽象书本类 abstract class AbstractBookTopic { abstract function getTopic(); abstract function getTitle(); abstract function setTitle($title_in); } // 书本类,继承自抽象书本类 class BookTopic extends AbstractBookTopic { private $topic; private $title; function __co

设计模式学习08:享元模式

设计模式学习08:享元模式 参考资料 https://www.jianshu.com/p/a2aa75939766 https://www.cnblogs.com/adamjwh/p/9070107.html 简介 Use sharing to support large numbers of fine-grained objects efficiently. 使用共享对象可有效地支持大量的细粒度的对象. 享元模式(Flyweight)又称为 轻量级模式,它是一种对象结构型模式. 面向对象技术可

设计模式之美学习-结构型-装饰者模式(二十)

什么是装饰者模式 在不破坏被装饰类的业务逻辑的情况下进行增强 同时支持装饰多层,与代理模式很像 装饰者侧重增强,代理侧重控制 Java IO 类图 使用 //FileInputStream是转为用于读取文件流的类 InputStream in = new FileInputStream("/user/wangzheng/test.txt"); //是一个支持带缓存功能的数据读取类 对in进行装饰实现增加 带有缓存 InputStream bin = new BufferedInputS

headfirst设计模式(3)—装饰者模式

序 好久没写设计模式了,自从写了两篇之后,就放弃治疗了,主要还是工作太忙了啊(借口,都是借口),过完年以后一直填坑,填了好几个月,总算是稳定下来了,可以打打酱油了. 为什么又重新开始写设计模式呢?学习使我快乐啊(我装逼起来我自己都害怕),其实主要是最近填坑的时候看源代码有点晕,很多代码不知道他们为什么要那么写啊,好气啊 当时第二篇写完,其实就在准备第三篇了,但是,一直也没有写,看了好几遍,但是一直掌握不到精髓(其实现在也掌握不到),感觉挺模糊的,也就一直拖啊拖,拖延症晚期患者已经不用抢救了...