设计模式篇——初探装饰器模式

文章目录

1、装饰器模式介绍

2、装饰器模式类图

3、装饰器模式Demo实现(一个小镇的拉面馆)

4、装饰器模式总结

装饰器模式介绍:装饰器模式可以在不修改任何底层代码的情况下,给对象赋予新的职责(程序运行时的扩展,动态的将责任附加到对象上)。属于结构型设计模式。

类图:

我们来看下装饰器模式的类图:

  

一个简单的Demo(故乡小镇的一个面馆):

  

在故乡的一个小镇上面,有一家面馆,主营拉面。在这里你可以只点清汤面(SoupNoodle),也可以往里面加佐料,佐料有牛肉(Beef),鱼丸(FishBall)还有菠菜(Spinach)。面馆今天开张了。

这里的所有面条都基于一个抽象类BaseNoodle来实现,这个抽象类有两个抽象方法,获取它的价格(double Price()),获取它的名字(string GetName())。

 1     /// <summary>
 2     /// 面条抽象类
 3     /// </summary>
 4     public abstract class BaseNoodle
 5     {
 6         /// <summary>
 7         /// 价格
 8         /// </summary>
 9         /// <returns></returns>
10         public abstract double Price();
11         /// <summary>
12         /// 获取名称
13         /// </summary>
14         /// <returns></returns>
15         public abstract string GetName();
16     }

BaseNoodle

然后让我们实现下我们最基础的清汤面(SoupNoodle),清汤面的价格是1块钱(嗯,还蛮实惠的)

 1     /// <summary>
 2     /// 清汤面
 3     /// </summary>
 4     public class SoupNoodle : BaseNoodle
 5     {
 6         private static double cost = 1;
 7         public override string GetName()
 8         {
 9             return "清汤面";
10         }
11         public override double Price()
12         {
13             return cost;
14         }
15     }

SoupNoodle

这时候,我们来了第一位客人(张三),他要一碗带牛肉作料的清汤面

于是乎,我们就实现了这样一个类。

 1     public class SoupNoodleWithBeef : BaseNoodle
 2     {
 3         private static double cost = 1;
 4         public override string GetName()
 5         {
 6             return "清汤面" + ",牛肉";
 7         }
 8         /// <summary>
 9         /// 假设牛肉一份0.6元
10         /// </summary>
11         /// <returns></returns>
12         public override double Price()
13         {
14             return cost + 0.6;
15         }
16     }

SoupNoodleWithBeef

然后第二个客人进来了,是个可爱的小姑娘,她要一份加菠菜的清汤面。于是乎,我们又要实现这样一个类。

 1     public class SoupNoodleWithSpinach : BaseNoodle
 2     {
 3         private static double cost = 1;
 4         public override string GetName()
 5         {
 6             return "清汤面" + ",菠菜";
 7         }
 8         /// <summary>
 9         /// 假设菠菜一份0.2元
10         /// </summary>
11         /// <returns></returns>
12         public override double Price()
13         {
14             return cost + 0.2;
15         }
16     }

SoupNoodleWithSpinach

我们一共有三种佐料,假设客人的口味都不同,那样的话我们需要多少个继承自BaseNoodle的子类呢? 没错,应该是A(3,3)个6个子类。这样显然不行,假如我们后期有添加了新的佐料,虾球,那样我们的子类个数就是24个,况且谁又能保证客人只点一份相同的佐料呢?假如点两份牛肉呢?我们的子类个数将呈现指数级别的增长。。。

这时候我们的装饰器模式就登场了。

还是我们的面条基类抽象类,和清汤面(被装饰者)类,在这个的基础之上我们将不再写很多针对细节的子类。我们首先实现一个佐料抽象类(SeasoningDecorator),这个抽象类也要继承自BaseNoodle。它内部有一个实例变量=》BaseNoodle

 1     /// <summary>
 2     /// 基础佐料类
 3     /// </summary>
 4     public abstract class SeasoningDecorator : BaseNoodle
 5     {
 6         private BaseNoodle _baseNoodle = null;
 7         public SeasoningDecorator(BaseNoodle baseNoodle)
 8         {
 9             _baseNoodle = baseNoodle;
10         }
11
12         public override string GetName()
13         {
14             return this._baseNoodle.GetName();
15         }
16
17         public override double Price()
18         {
19             return this._baseNoodle.Price();
20         }
21     }

SeasoningDecorator

此时,我们定义我们的具体佐料类,这些佐料类都继承自SeasoningDecorator,而且内部都存在一个实例变量=》BaseNoodle。

 1     /// <summary>
 2     /// 牛肉
 3     /// </summary>
 4     public class BeefDecorator: SeasoningDecorator
 5     {
 6         private static double cost = 0.6;
 7         private BaseNoodle _baseNoodle = null;
 8         public BeefDecorator(BaseNoodle baseNoodle) : base(baseNoodle)
 9         {
10             _baseNoodle = baseNoodle;
11         }
12         public override string GetName()
13         {
14             return this._baseNoodle.GetName() +  ",牛肉";
15         }
16         public override double Price()
17         {
18             return this._baseNoodle.Price() + cost;
19         }
20     }

BeefDecorator

 1     /// <summary>
 2     /// 鱼丸
 3     /// </summary>
 4     public class FishBallDecorator : SeasoningDecorator
 5     {
 6         private static double cost = 0.4;
 7         private BaseNoodle _baseNoodle = null;
 8         public override string GetName()
 9         {
10             return this._baseNoodle.GetName() + ",鱼丸";
11         }
12         public FishBallDecorator(BaseNoodle baseNoodle) : base(baseNoodle)
13         {
14             _baseNoodle = baseNoodle;
15         }
16         public override double Price()
17         {
18             return this._baseNoodle.Price() + cost;
19         }
20     }

FishBallDecorator

 1    /// <summary>
 2     /// 菠菜
 3     /// </summary>
 4     public class Spinach : SeasoningDecorator
 5     {
 6         private static double cost = 0.2;
 7         private BaseNoodle _baseNoodle = null;
 8         public override string GetName()
 9         {
10             return this._baseNoodle.GetName() + ",菠菜";
11         }
12         public Spinach(BaseNoodle baseNoodle) : base(baseNoodle)
13         {
14             _baseNoodle = baseNoodle;
15         }
16         public override double Price()
17         {
18             return this._baseNoodle.Price() + cost;
19         }
20     }

Spinach

这些具体的佐料类就是我们的装饰器。因为它构造函数接收一个BaseNoodle,所以我们可以这样来实现对清汤面(SoupNoodle)的装饰:

 1             //定义清汤面
 2             BaseNoodle baseSoupNoodle = new SoupNoodle();
 3             //添加一份牛肉
 4             baseSoupNoodle = new BeefDecorator(baseSoupNoodle);
 5             //添加一份鱼丸
 6             baseSoupNoodle = new FishBallDecorator(baseSoupNoodle);
 7             //添加一份菠菜
 8             baseSoupNoodle = new Spinach(baseSoupNoodle);
 9             //再添加一份牛肉
10             baseSoupNoodle = new BeefDecorator(baseSoupNoodle);
11             Console.WriteLine($"点了一份{baseSoupNoodle.GetName()},价格为{baseSoupNoodle.Price()}");
12             Console.Read();

点餐

装饰器模式总结:

  • 装饰器属于结构型设计模式,很好的遵循了开闭原则。
  • 装饰器模式的装饰者与被装饰者有相同的超类型。
  • 装饰器模式可以在程序运行时,以组合的方式,动态的给对象添加行为(因为有相同的超类型,所以任何需要原始对象的场合,都可以用装饰过的对象去替代它)。
  • 装饰器模式会出现很多的小的类型。

原文地址:https://www.cnblogs.com/liumengchen-boke/p/8725812.html

时间: 2024-10-11 10:41:30

设计模式篇——初探装饰器模式的相关文章

设计模式(三)_装饰器模式

上篇学习了策略模式,现在回想下,什么是策略模式,好了.本篇主要介绍装饰器模式,just do it! 什么是装饰器模式 装饰器模式指的是动态的将责任附加到对象上.若要扩展功能,装饰器模式提供了比继承更弹性的替代方案. 如何使用装饰器模式 老王来到商场买衣服,需要买衣服,裤子,帽子...... public class Wang { public void show(){ System.out.println("我穿上衣服,累计花费100元"); System.out.println(&

【设计模式】之装饰器模式

为什么会有装饰模式? 装饰模式是为了解决继承强依赖性和出现大量子类不方便管理问题而出现的.   1. 概述 动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更灵活. 原理:增加一个修饰类包裹原来的类,包裹的方式一般是通过在将原来的对象作为修饰类的构造函数的参数.装饰类实现新的功能,但是,在不需要用到新功能的地方,它可以直接调用原来的类中的方法.修饰类必须和原来的类有相同的接口. 2. 模式中的角色 2.1 抽象构建(Component):定义一个抽象接口,用以给这些对象动态

设计模式入门之装饰器模式Decorator

//装饰模式定义:动态地给一个对象加入一些额外的职责. //就添加功能来说.装饰模式比生成子类更为灵活 //这也提现了面向对象设计中的一条基本原则,即:尽量使用对象组合,而不是对象继承 //Component:组件对象的接口.能够给这些对象动态加入职责 //ConcreateComponet:详细的组件对象.实现组件对象接口.通常就是被装饰器装饰的对象.也就是能够给这个对象加入职责 //Decorator:全部装饰器的抽象父类,须要定义一个与组件接口一致的接口,并持有一个Component对象,

《设计模式》之装饰器模式

装饰器模式 装饰器模式中主要有两个角色: 装饰器(夹克,帽子) 被装饰的对象(老王) 装饰器和被装饰的对象有两个特点,也是装饰器模式的关键: 他们实现同一个接口 装饰器中使用了被装饰的对象 使用: /** * <p> *定义一个接口 * </p> * * @author aodeng-低调小熊猫 * @since 19-7-11 */ public interface Person { /** * 计算累计消费 * @return */ public Double cost();

装饰器模式与代理模式比较

当有这样的业务需求的时候——要为写好的代码在目标代码之前或者之后添加部分操作时,此时最笨的方法就是直接在目标代码的前后加上我们需要的功能代码,但是这样违背了java封装的特性.更好一点的方法就是使用设计模式——代理模式,然而,装饰器模式也有同类的功能,那么着两种设计模式到底有什么区别呢?下面就分别来学习一下这两种设计模式. 装饰器模式类图如下: 该类图包括几个部分:一个接口(装饰器与需要被装饰的实体类都需要实现该接口,公用方法在该接口中定义),一个实现类,一个装饰器的接口,具体实现的装饰器. 在

Java进阶篇设计模式之五-----外观模式和装饰器模式

前言 在上一篇中我们学习了结构型模式的适配器模式和桥接模式.本篇则来学习下结构型模式的外观模式和装饰器模式. 外观模式 简介 外观模式隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口.这种类型的设计模式属于结构型模式,它向现有的系统添加一个接口,来隐藏系统的复杂性. 简单的来说就是对外提供一个简单接口,隐藏实现的逻辑.比如常用电脑的电源键,我们只需按电源键,就可以让它启动或者关闭,无需知道它是怎么启动的(启动CPU.启动内存.启动硬盘),怎么关闭的(关闭硬盘.关闭内存.关闭CPU)

【一起学设计模式】状态模式+装饰器模式+简单工厂模式实战:(一)提交个订单我到底经历了什么鬼?

前言 之前在我的博客(一枝花算不算浪漫)中已经更新过两篇设计模式相关的内容 [一起学设计模式]策略模式实战一:基于消息发送的策略模式实战 [一起学习设计模式]策略模式实战二:配合注解 干掉业务代码中冗余的if else... [一起学设计模式]访问者模式实战:权限管理树删节点操作 [一起学设计模式]命令模式+模板方法+工厂方法实战: 如何优雅的更新商品库存... 上面内容都是基于真实业务场景精简后的设计(工作中真实场景使用到的). 之前为了学习设计模式,看过网上很多相关博客讲解,大都是画下UML

IOS设计模式之二(门面模式,装饰器模式)

本文原文请见:http://www.raywenderlich.com/46988/ios-design-patterns. 由 @krq_tiger(http://weibo.com/xmuzyq)翻译,如果你发现有什么错误,请与我联系谢谢. 门面(Facade)模式(译者注:facade有些书籍译为门面,有些书籍译为外观,此处译为门面) 门面模式针对复杂的子系统提供了单一的接口,不需要暴漏一些列的类和API给用户,你仅仅暴漏一个简单统一的API. 下面的图解释了这个概念: 这个API的使用者

python设计模式之装饰器模式

装饰器模式 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构.这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装. 这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能. import time def log_calls(func): def wrapper(*args,**kwargs): now=time.time() print("Calling{0} with {1} and {2}