C#设计模式(七)装饰者模式

来源:互联网 发布:淘宝聚划算报名要求 编辑:程序博客网 时间:2024/06/07 14:04

一、引言

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

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

2.1 定义

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

2.2 装饰者模式实现

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

class Program    {        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();        }        /// <summary>        /// 手机抽象类,即装饰者模式中的抽象组件类        /// </summary>        public abstract class Phone        {            public abstract void Print();        }        /// <summary>        /// 苹果手机,即装饰着模式中的具体组件类        /// </summary>        public class ApplePhone:Phone        {            public override void Print()            {                Console.WriteLine("Apple Phone");            }        }        public abstract class Decorator:Phone        {            private Phone phone;            public Decorator(Phone p)            {                this.phone = p;            }            public override void Print()            {                if (phone != null)                {                    phone.Print();                }            }        }        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>        /// 手机挂件继承Decorate有构造函数必须显示调用        /// </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("现在苹果手机有漂亮的挂件了");            }        }    }

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


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

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

 

三、装饰者模式的优缺点

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

优点:

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

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

语法知识:C#的构造函数

1、构造函数不继承,派生类会自动调用基类构造函数。2、若类内没有定义构造函数,系统会自动隐式生成一个不带参数的构造函数,比如定义一个类:public class A{ }可以理解为它已经存在一个如下的构造函数public class A{    public A()    {           }}3、派生类构造函数自动调用基类的不带参数的构造函数,注意下面的格式public class B:A{    public B()    {           }}相当于public class B:A{    public B():base()    {           }}3、基类中带参数的构造函数必须显式调用,比如:public class A{    public A()    {           }    public A(string str)    {           }}public class B:A{    public B():base("aaa")    {           }}

0 0
原创粉丝点击