首页 > 代码库 > 设计模式之装饰者模式

设计模式之装饰者模式

Decorator

装饰者模式:

类图如下:

技术分享

 

注意:

1. Decorator继承于Component【IS A关系】, 继承的目的是使用装饰者和被装饰都拥有相同的接口。这样用户可以统一的把它们看作成Component,操作起来没有不同

2. Decorator又维护一个指向Component实例的引用【HAS A关系】。HAS A Component的目的是让ConcreteDecorator可以在运行时动态给ConcreteComponent增加职责

也就是说,Decorator跟Component之间,既有静态继承关系又有动态组合关系,

装饰者模式通过继承实现统一了装饰者和被装饰者的接口,通过组合获得了在运行时动态扩展被装饰者对象的能力。

来看一下代码:

    /// <summary>
    /// 酒店服务
    /// </summary>
    public interface IHotelService
    {
        /// <summary>
        /// 客房预订
        /// </summary>
        void Booking();
    }

    public class HotelService : IHotelService
    {
        public void Booking()
        {
            // 业务逻辑。。。
        }
    }


    public abstract class DecoratorService : IHotelService
    {
        private IHotelService hotelService;

        public DecoratorService(IHotelService hotelService)
        {
            this.hotelService = hotelService;
        }

        public virtual void Booking()
        {
            if (this.hotelService != null)
            {
                this.hotelService.Booking();
            }
        }
    }

    /// <summary>
    /// 携程服务给酒店预订增加了服务
    /// </summary>
    public class CtripService : DecoratorService
    {
        public CtripService(IHotelService hotelService) : base(hotelService)
        {
        }

        public override void Booking()
        {
            this.Before();

            base.Booking();

            this.After();
        }

        public void Before()
        {
            //租车 + 早餐 + 保险
        }

        public void After()
        {
            //景点门票+其他费用
        }

    }

    /// <summary>
    /// 去哪儿服务给酒店预订增加了服务
    /// </summary>
    public class QunarService : DecoratorService
    {
        public QunarService(IHotelService hotelService) : base(hotelService)
        {
        }

        public override void Booking()
        {
            this.Before();

            base.Booking();

            this.After();
        }

        public void Before()
        {
            //租车 + 早餐 + 保险
        }

        public void After()
        {
            //景点门票+其他费用
        }

    }


    public class Customer
    {
        public void Travel()
        {

            IHotelService hotelService = new HotelService();

            DecoratorService ctripService = new CtripService(hotelService);
            // 如使用第三方的服务:携程,势必要加一些其他的“服务”项目。。。。。
            ctripService.Booking();

            DecoratorService qunarService = new QunarService(hotelService);
            // 如使用第三方的服务:去哪儿,势必要加一些其他的“服务”项目。。。。。
            qunarService.Booking();

        }
    }

 

首先,实例化酒店服务,这是我们最想要的服务。

其次,我们可以根据第三方服务公司的服务项目选择服务公司,同时把酒店实例传入。

最后,我们就可预定服务了,同时也预定了第三方的服务。

通过继承,我们使去哪和携程都拥有了相同的预定服务接口,

通过组合,我们在酒店服务的基础上扩展了服务项目。

 

说到这儿,我感觉装饰者模式和代理模式好像,因为上一篇,我刚写完代理模式,

都是可以在原有功能的基础上扩展功能。仔细想了想,还有有些区别的,于是,我特意用这两个模式分别来实现酒店预订功能,来看到底有什么区别:

1. 代理模式中,用户对HotelService是透明的,也是不关心它的, HotelService是由 代理对象proxy来创建和维护的。

    装饰者模式中,是由用户来创建HotelService的,再把它传给具体的装饰者。

    可以理解为,代理模式中,代理是知道我要创建谁,而装饰者是不知道我要创建谁,需要你来告诉我。也就是说只要是满足IHotelService接口的,我都可以装饰它。

2. 从类图,我们可以看出,代理对象只有一个,而装饰对象可以有多个,如果代理对象可以是多少,我觉得可以就演变成装饰者模式了。

 

综上,我认为代理模式和装饰者模式,在一定的条件下,是可以相互转化的。

 

设计模式之装饰者模式