关闭

扩展系统功能——装饰模式

标签: 设计模式装饰模式
333人阅读 评论(0) 收藏 举报
分类:

一、引言

在软件开发中,我们经常想要对一类对象添加不同的功能,例如要给手机添加贴膜,手机挂件,手机外壳等,如果此时利用继承来实现的话,就需要定义无数的类,如StickerPhone(贴膜是手机类)、AccessoriesPhone(挂件手机类)等,这样就会导致 ”子类爆炸“问题,为了解决这个问题,我们可以使用装饰者模式来动态地给一个对象添加额外的职责。下面让我们看看装饰者模式。

二、装饰者模式的详细介绍

2.1 定义

装饰者模式以对客户透明的方式动态地给一个对象附加上更多的责任,装饰者模式相比生成子类可以更灵活地增加功能。

2.2 装饰者模式实现

这里以手机和手机配件的例子来演示装饰者模式的实现,具体代码如下:

/// <summary>
    /// 手机抽象类,即装饰者模式中的抽象组件类
    /// </summary>
    public abstract class Phone
    {
        public abstract void Print();
    }
 
    /// <summary>
    /// 苹果手机,即装饰着模式中的具体组件类
    /// </summary>
    public class ApplePhone:Phone
    {
        /// <summary>
        /// 重写基类方法
        /// </summary>
        public override void Print()
        {
            Console.WriteLine("开始执行具体的对象——苹果手机");
        }
    }
 
    /// <summary>
    /// 装饰抽象类,要让装饰完全取代抽象组件,所以必须继承自Photo
    /// </summary>
    public abstract class Decorator:Phone
    {
        private Phone phone;
 
        public Decorator(Phone p)
        {
            this.phone = p;
        }
 
        public override void Print()
        {
            if (phone != null)
            {
                phone.Print();
            }
        }
    }
 
    /// <summary>
    /// 贴膜,即具体装饰者
    /// </summary>
    public class Sticker : Decorator
    {
        public Sticker(Phone p)
            : base(p)
        { 
        }
 
        public override void Print()
        {
            base.Print();
 
            
// 添加新的行为
            AddSticker();      
        }
 
        /// <summary>
        /// 新的行为方法
        /// </summary>
        public void AddSticker()
        {
            Console.WriteLine("现在苹果手机有贴膜了");
        }
    }
 
    /// <summary>
    /// 手机挂件
    /// </summary>
    public class Accessories : Decorator
    {
        public Accessories(Phone p)
            : base(p)
        {
        }
 
        public override void Print()
        {
            base.Print();
 
            
// 添加新的行为
            AddAccessories();          
        }
 
        /// <summary>
        /// 新的行为方法
        /// </summary>
        public void AddAccessories()
        {
            Console.WriteLine("现在苹果手机有漂亮的挂件了");
        }
    }
此时客户端调用代码如下:

class Customer
    {
        static void Main(string[] args)
        {
            
// 我买了个苹果手机
            Phone phone = new ApplePhone();
 
            
// 现在想贴膜了
            Decorator applePhoneWithSticker = new Sticker(phone);
            
// 扩展贴膜行为
            applePhoneWithSticker.Print();
            Console.WriteLine("----------------------\n");
 
            
// 现在我想有挂件了
            Decorator applePhoneWithAccessories = new Accessories(phone);
            
// 扩展手机挂件行为
            applePhoneWithAccessories.Print();
            Console.WriteLine("----------------------\n");
 
            
// 现在我同时有贴膜和手机挂件了
            Sticker sticker = new Sticker(phone);
            Accessories applePhoneWithAccessoriesAndSticker = new Accessories(sticker);
            applePhoneWithAccessoriesAndSticker.Print();
            Console.ReadLine();
        }

从上面的客户端代码可以看出,客户端可以动态地将手机配件增加到手机上,如果需要添加手机外壳时,此时只需要添加一个继承Decorator的手机外壳类,从而,装饰者模式扩展性也非常好。

2.3 装饰者模式的类图

实现完了装饰者模式之后,让我们看看装饰者模式实现中类之间的关系,具体见下图:


在装饰者模式中各个角色有:

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

 

三、装饰者模式的优缺点

看完装饰者模式的详细介绍之后,我们继续分析下它的优缺点。

优点:

  1. 装饰这模式和继承的目的都是扩展对象的功能,但装饰者模式比继承更灵活
  2. 通过使用不同的具体装饰类以及这些类的排列组合,设计师可以创造出很多不同行为的组合
  3. 装饰者模式有很好地可扩展性

缺点:装饰者模式会导致设计中出现许多小对象,如果过度使用,会让程序变的更复杂。并且更多的对象会是的差错变得困难,特别是这些对象看上去都很像。

四、使用场景

下面让我们看看装饰者模式具体在哪些情况下使用,在以下情况下应当使用装饰者模式:

  1. 需要扩展一个类的功能或给一个类增加附加责任。
  2. 需要动态地给一个对象增加功能,这些功能可以再动态地撤销。
  3. 需要增加由一些基本功能的排列组合而产生的非常大量的功能

五、总结

到这里,装饰者模式的介绍就结束了,装饰者模式采用对象组合而非继承的方式实现了再运行时动态地扩展对象功能的能力,而且可以根据需要扩展多个功能,避免了单独使用继承带来的 ”灵活性差“和”多子类衍生问题“。同时它很好地符合面向对象设计原则中 ”优先使用对象组合而非继承“和”开放-封闭“原则。

 

本专题所有源码:设计模式之装饰者模式




0
0
查看评论

设计模式学习之路 - 装饰者模式 - 动态扩展器

今天了解下装饰者模式。 首先,看下需求。 一家咖啡厅需要做一个订单系统,为了配合他们的饮料供应需求。 首先有一个超类,饮料类。 package com.chris.decorator; public abstract class Beverage { String description = &...
  • wuxingchris
  • wuxingchris
  • 2016-07-21 10:21
  • 375

扩展系统功能——装饰模式

转:http://blog.csdn.net/lovelion/article/details/7424685
  • lynchyo
  • lynchyo
  • 2014-08-22 14:24
  • 306

扩展系统功能——装饰模式(三)

12.3 完整解决方案        为了让系统具有更好的灵活性和可扩展性,克服继承复用所带来的问题,Sunny公司开发人员使用装饰模式来重构图形界面构件库的设计,其中部分类的基本结构如图12-4所示: 图12...
  • wangeclipse
  • wangeclipse
  • 2013-12-10 00:56
  • 454

扩展系统功能——装饰模式(二)

12.2 装饰模式概述       装饰模式可以在不改变一个对象本身功能的基础上给对象增加额外的新行为,在现实生活中,这种情况也到处存在,例如一张照片,我们可以不改变照片本身,给它增加一个相框,使得它具有防潮的功能,而且用户可以根据需要给它增加...
  • wangeclipse
  • wangeclipse
  • 2013-12-10 00:55
  • 447

扩展系统功能——装饰模式(四)

12.4 透明装饰模式与半透明装饰模式       装饰模式虽好,但存在一个问题。如果客户端希望单独调用具体装饰类新增的方法,而不想通过抽象构件中声明的方法来调用新增方法时将遇到一些麻烦,我们通过一个实例来对这种情况加以说明: ...
  • wangeclipse
  • wangeclipse
  • 2013-12-10 00:56
  • 459

扩展系统功能--装饰模式

根据合成复用原则,在实现功能复用时,应该多用关联,少用继承。 装饰模式可以在不改变一个对象本身功能的基础上给对象增加额外的新行为。 装饰模式是一种用于替代继承的技术,通过一种无须定义子类的方式来给对象动态增加职责,使用对象之间的关联关系取代类之间的继承关系。 在装饰模式中,为了让系统具有更好的灵活...
  • laoj1228
  • laoj1228
  • 2017-02-22 20:11
  • 142

扩展系统功能--装饰模式

对已有对象的功能进行扩展(装饰),以获得更加符合用户需求的对象,使得对象具有更加强大的功能,这就是装饰模式。 基于继承的复用缺点: (1) 系统扩展麻烦,在某些编程语言中无法实现(多继承问题)。 (2) 代码重复,不利于对系统进行修改和维护。 (3) 系统庞大,类的数目非常多。 装饰模式概述 ...
  • sxh850297968
  • sxh850297968
  • 2015-07-14 20:18
  • 629

扩展系统功能--装饰模式(Decorator)

顾名思义,装饰模式就是给一个对象增加一些新的功能,而且是动态的,要求装饰对象和被装饰对象实现同一个接口,装饰对象持有被装饰对象的实例,关系图如下:设计初衷:通常可以使用继承来实现功能的拓展,如果这些需要拓展的功能的种类很繁多,那么势必生成很多子类,增加系统的复杂性,同时,使用继承实现功能拓展,我们必...
  • cds86333774
  • cds86333774
  • 2016-03-22 00:49
  • 207

装饰模式 -- 扩展系统功能

尽管目前房价依旧很高,但还是阻止不了大家对新房的渴望和买房的热情。如果大家买的是毛坯房,无疑还有一项艰巨的任务要面对,那就是装修。对新房进行装修并没有改变房屋用于居住的本质,但它可以让房子变得更漂亮、更温馨、更实用、更能满足居家的需求。在软件设计中,我们也有一种类似新房装修的技术可以对已有对象(新房...
  • u013233468
  • u013233468
  • 2014-01-14 16:28
  • 400

扩展系统功能——装饰模式(一)

尽管目前房价依旧很高,但还是阻止不了大家对新房的渴望和买房的热情。如果大家买的是毛坯房,无疑还有一项艰巨的任务要面对,那就是装修。对新房进行装修并没有改变房屋用于居住的本质,但它可以让房子变得更漂亮、更温馨、更实用、更能满足居家的需求。在软件设计中,我们也有一种类似新房装修的技术可以对已有对象(新房...
  • wangeclipse
  • wangeclipse
  • 2013-12-10 00:55
  • 409
    个人资料
    • 访问:321387次
    • 积分:4681
    • 等级:
    • 排名:第7395名
    • 原创:150篇
    • 转载:93篇
    • 译文:0篇
    • 评论:42条
    最新评论
    我的小窝