• 设计模式之装饰者模式


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

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

  • 相关阅读:
    机器学习系列(4) 线性回归
    MYSQL系列(5) 电商常用指标查询
    MYSQL系列(4) 关于时间函数的一些写法
    快速排序
    选择排序
    希尔排序
    直接插入排序
    冒泡排序
    Java修饰符大汇总
    字符串实现大数的相加
  • 原文地址:https://www.cnblogs.com/hankuikui/p/6995394.html
Copyright © 2020-2023  润新知