设计模式:装饰者模式

  设计模式系列目录

  装饰者模式么,在生活中我们是经常接触的。比如像我们这么快节奏的生活,好多都是早上去买煎饼。一般我们会这么说:“来一个粗粮煎饼,加两个鸡蛋加一根肠

或者:“来个山东煎饼,只加土豆丝”等等。“煎饼” 就是这个么个有弹性的对象,面饼是不变的,其它的像鸡蛋,肠什么的者在装饰面饼。这个也是我们编程时的一个设计原则

对扩展开放,对修改关闭。(在最后我会给出C# 和C++ 两种代码示例)

  装饰者模式和“煎饼”差不多,它可以动态地将责任("鸡蛋“、“肠”...)附加到对象(”煎饼“)上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。

  我们看一下装饰者模式的类图:

  

看这个类图我们可以总结一下装饰者模式的特点:

1.被装饰对象和装饰品有相同的接口。这样装饰品和被装饰对象就可以相互交互。

2.装饰品对象包含一个被装饰对象的引用。

让我们做一个煎饼吧:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DecoratorDemo
{
    [Flags]
    public enum BcType
    {
        None = 0,       // 0
        SdCakeType,     // 山东煎饼
        EggType,        // 蛋
        SausageType     // 肠
    }

    public interface IBatterCake
    {
        List<BcType> Type();
        double Coast();
    }

    public class NoneBatterCake : IBatterCake
    {
        public List<BcType> Type()
        {
            return new List<BcType> {BcType.None};
        }

        public double Coast()
        {
            return 0;
        }
    }

    /// <summary>
    /// 山东煎饼
    /// </summary>
    public class SdBatterCake : IBatterCake
    {
        public List<BcType> Type()
        {
            return new List<BcType> {BcType.SdCakeType};
        }

        public double Coast()
        {
            return 3.5;
        }
    }

    /// <summary>
    /// 鸡蛋
    /// </summary>
    public class Egg : IBatterCake
    {
        private readonly IBatterCake _batterCake = new NoneBatterCake();

        public Egg(IBatterCake mMoney)
        {
            _batterCake = mMoney;
        }

        public List<BcType> Type()
        {
            List<BcType> types = _batterCake.Type();
            types.AddRange(new List<BcType>() { BcType.EggType });
            return types;
        }

        public double Coast()
        {
            return 1 + _batterCake.Coast();
        }
    }

    /// <summary>
    /// 肠
    /// </summary>
    public class Sausage : IBatterCake
    {
        private readonly IBatterCake _batterCake = new NoneBatterCake();

        public Sausage(IBatterCake mMoney)
        {
            _batterCake = mMoney;
        }

        public List<BcType> Type()
        {
            List<BcType> types = _batterCake.Type();
            types.AddRange(new List<BcType>() { BcType.SausageType });
            return types;
        }

        public double Coast()
        {
            return 2 + _batterCake.Coast();
        }
    }

    /// <summary>
    /// 计算花费
    /// </summary>
    public class CalculateMoney : IBatterCake
    {
        private readonly IBatterCake _batterCake = new NoneBatterCake();
        public CalculateMoney(IBatterCake mMoney)
        {
            _batterCake = mMoney;
        }

        public List<BcType> Type()
        {
            return new List<BcType> {BcType.None};
        }

        public string Description()
        {
            List<BcType> types = _batterCake.Type();

            int eggs = 0, sausage = 0,battercakies = 0;
            for (int index = 0, count = types.Count(); index < count; index++)
            {
                if (types[index] == BcType.SdCakeType)
                    battercakies++;

                if (types[index] == BcType.EggType)
                    eggs++;

                if (types[index] == BcType.SausageType)
                    sausage++;
            }
            StringBuilder description = new StringBuilder();
            if (battercakies > 0)
                description.Append("煎饼").Append(battercakies).Append("个").Append("\n");

            if (eggs > 0)
                description.Append("鸡蛋").Append(eggs).Append("个").Append("\n");

            if (sausage > 0)
                description.Append("烤肠").Append(sausage).Append("个").Append("\n");

            return description.ToString();
        }

        public double Coast()
        {
            return _batterCake.Coast();
        }
    }

    public class Program
    {
        private static void Main(string[] args)
        {
            // 一个山东煎饼
            IBatterCake sdBatterCake = new SdBatterCake();
            // 一个鸡蛋
            IBatterCake egg1 = new Egg(sdBatterCake);
            // 再来个鸡蛋
            IBatterCake egg2 = new Egg(egg1);
            // 再来个肠
            IBatterCake sausage = new Sausage(egg2);

            CalculateMoney calculateMoney = new CalculateMoney(sausage);

            Console.WriteLine(calculateMoney.Description());
            Console.WriteLine("共花费 : {0}", calculateMoney.Coast());
            Console.ReadLine();
        }
    }
}

看一下结果:

以下情况使用Decorator模式

1. 需要扩展一个类的功能,或给一个类添加附加职责。

2. 需要动态的给一个对象添加功能,这些功能可以再动态的撤销。

3. 需要增加由一些基本功能的排列组合而产生的非常大量的功能,从而使继承关系变的不现实。

4. 当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。

时间: 2024-08-04 22:04:59

设计模式:装饰者模式的相关文章

【笔记】设计模式——装饰者模式

实现一个类似QQavator功能的代码 1.原始实现 1 //存在的问题: 2 //1.wear*方法出现重复代码,可以重构:实质上为代码结构一致,输出内容相同,可以通过在定义一个基类,在基类中定义抽象的Wear*,在子类中重写: 3 //2.倘若需求中新增某种服饰,需要修改Person类代码,不符合开放--封闭原则: 4 //3.客户端中代码暴露了具体装饰细节,理想情况下只需要提供装饰顺序,装饰细节封装起来: 5 class Person 6 { 7 private string name;

设计模式 - 装饰者模式(Decorator Pattern) Java的IO类 使用方法

装饰者模式(Decorator Pattern) Java的IO类 使用方法 本文地址: http://blog.csdn.net/caroline_wendy/article/details/26716823 装饰者模式(decorator pattern)参见: http://blog.csdn.net/caroline_wendy/article/details/26707033 Java的IO类使用装饰者模式进行扩展, 其中FilterInputStream类, 就是装饰者(decora

java设计模式------装饰着模式

java设计模式-------装饰者模式 装饰者模式 Decorator模式(别名Wrapper):动态将职责附加到对象上,若要扩展功能,装饰者提供了比继承更具弹性的代替方案.主要有组件(components)和装饰器(Decorator)组成.要求components和Decorator实现相同的接口或者抽象类(具体类的局限性太大). 设计原则.模式特点.适用性 - 1. 多用组合,少用继承. 利用继承设计子类的行为,是在编译时静态决定的,而且所有的子类都会继承到相同的行为.然而,如果能够利用

设计模式---装饰者模式(学习笔记)

首先看装饰者模式的定义:动态的将责任附加到对象上.若要扩展功 能,装饰者提供了比继承更有弹性的替代方案! 先看看<大话设计模式>给出的类图: 实际上,装饰者模式就是:把装饰者对象当成"包装者",换言之,把要装饰的对象作为参数传递到装饰对象里去,然后进行操作.(如果理解不对,希望给指正),下面看代码来理解这个类图: 这是装饰者和需要装饰的具体对象共同的接口: public abstract class Component { abstract void Operation()

设计模式 - 装饰者模式(Decorator Pattern) 详解

装饰者模式(Decorator Pattern) 详解 本文地址: http://blog.csdn.net/caroline_wendy/article/details/26707033 装饰者模式(Decorator Pattern):动态地将责任附加到对象上. 若要扩展功能, 装饰者提供了比继承更有弹性的替代方案. 使用方法: 1. 首先创建组件(Component)父类, 所有类,具体组件(Concrete Component)和装饰者(Decorator)都属于这一类型, 可以进行扩展

Java设计模式——装饰者模式

JAVA 设计模式 装饰者模式 用途 装饰者模式 (Decorator) 动态地给一个对象添加一些额外的职责.就增加功能来说,Decorator 模式相比生成子类更为灵活. 装饰者模式是一种结构式模式. 结构 图-装饰者模式结构图 Component : 定义一个对象接口,可以给这些对象动态地添加职责. interface Component {     public void operation(); } ConcreteComponent : 实现 Component 定义的接口. clas

5分钟读书笔记之 - 设计模式 - 装饰者模式

本章讨论的是一种为对象增添特性的技术,它并不使用创建新子类这种手段. 装饰者模式可以透明地把对象包装在具有同样接口的另一对象之中,这样一来,你可以给一些方法添加一些行为,然后将方法调用传递给原始对象.相对于创建子类来说,使用装饰者模式对象是一种更灵活的选择. 装饰者可用于为对象增加功能.它可以用来替代大量子类. 考虑前面的自行车类,你现在可能提供一些配件供用户选择,装饰者模式要求我们只需要创建选件类,这些类与四种自行车类都要实现Bicycle接口,但是他们只被用作这些自行车类的包装类.在这个例子

说说设计模式~装饰器模式(Decorator)

装饰器模式,也叫又叫装饰者模式,顾名思义,将一个对象进行包裹,包装,让它变成一个比较满意的对象,这种模式在我们平时项目开发中,经常会用到,事实上,它是处理问题的一种技巧,也很好的扩展了程序,让程序代码不那么死板! 何时能用到它? 1. 需要扩展一个类的功能,或给一个类添加附加职责. 2. 需要动态的给一个对象添加功能,这些功能可以再动态的撤销. 3. 需要增加由一些基本功能的排列组合而产生的非常大量的功能,从而使继承关系变的不现实. 4. 当不能采用生成子类的方法进行扩充时. 其中我们认为第四种

PHP设计模式-装饰器模式

1.概念: 装饰器模式又叫做装饰者模式,是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能.传统的编程模式都是子类继承父类实现方法的重载,使用装饰器模式,只需添加一个新的装饰器对象,更加灵活,避免类数目和层次过多. 2.角色: Component(被装饰对象基类):定义一个对象接口,以规范准备接受附加责任的对象. ConcreteComponent(具体被装饰对象):具体组件角色,即将要被装饰增加功能的类. Decorator(装饰者基类):装饰器接口. ConcreteDecor

java设计模式-装饰者模式

定义: 在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能.它是通过创建一个包装对象,也就是装饰来包裹真实的对象. 概述: 1.装饰者和被装饰对象有相同的超类型. 2.你可以用一个或多个装饰者包装一个对象. 3.既然装饰者和被装饰对象有相同的超类型,所以在任何需要原始对象(被包装的)的场合 ,可以用装饰过的对象代替它. 4.装饰者可以在所委托被装饰者的行为之前与/或之后,加上自己的行为,以达到特定的目的. 5.对象可以在任何时候被装饰,所以可以在运行时动态地.不限量地用你喜欢的装饰者