• 装饰模式(完全体会了此模式含义)


    第二次分析感受:

    看了下第一次分析。基本是把握到了本质。没有什么偏差。

    补充下使用场景需求

    1.原对象类必须存在,

    2.需要动态组合新功能。

    所以下面是推导模式的流程:

    所以我们最初的考虑会是添加一个接口,再通过继承复写接口功能来扩展功能。

    但是这个继承必须是组合形式的继承。因为需要在原功能的基础上扩展。所以还必须包含原对象。但是这样的话接口就没有强制性了(不能强制要求接口的派生类包含原对象)

    所以可以用虚类,定义一个原对象成员变量。而虚类和被装饰的类都派生于同一接口(包含我们需要扩展的函数)。就解决了。

    第一次分析:

    这个模式也是之前没看懂。

    需要看懂的话,要给自己提明确需求。之前没看懂就是因为很多书没有告诉你,为什么要放弃简单的方案。估计那些作者也没有深刻体会吧。

    如,一个战士有形象展示。需要给个方案,可以灵活的加特效,如加个冰背景,火背景等。

    先不要装b,最开始一定会是直接在类里面加方法。 结果,非常ok。如果你也满意,同事,客户都满意,而且以后改动都不大。那么装饰模式可以根本不要学习。估计你一辈子都用不到。

    非常特特特殊情况。装饰动作太繁多,改动太频繁。那么才需要装饰模式。

    新的要求。不要在类里面修改。把修改踢到类的外面。 那么逼迫自己想方案。

    你会尝试很多方案,大多数都是错误的。

    这个方案最起码有几点。

    1必须输入输出都是原来的对象。不管你用函数,接口。虚类。各种技术都行,开始别confine自己。

    2.需要对原来对象的某个方法复写。

    3.继承的写法,是不行的,因为需要无穷的类。想想加火的特效。如果是效果是一点一点的加,想想看。要1000个火特效,需要继承1000次。中间再差点其他特效,而且顺序有关。简直无解。

    4.基本上会逼迫你走向一个虚类继承被装饰类,并包含一个被装饰类对象。这样就为形成链条做好了准备,因为包含的是被装饰类,那么最初可以放入基础被装饰类,之后又可以把被装饰类的派生类放进去,形成一个装饰类的派生类,而它又可以放入到。。。

    当方法复写的时候。调用包含的装饰类对象的方法。 只有这个时候你才明白,哦,这是装饰模式。才会发现,原来装饰模式这么巧妙。

    包含被装饰类,并覆盖方法,调用被装饰类的方法,这个是完成了装饰的目的,比较容易推出来。而最后虚类继承被装饰类,是一个神来之笔。巧妙。

    装饰模式从某种意义上,也是对组合方式的支持,继承固定性,无法满足。可以想象为最后展示战士的时候,是一个战士经过一个又一个类,这些类,只是把自己包裹了一下,并对某个方法包装了一下。

    个人觉得,除非是真的体现了装饰功能,意思就是多变,否则可以用继承。

    而且你对代码要求高,否则可以把新的装饰功能,放入到类中。

    总结,非常巧妙的模式,和工厂方法一样。都非常巧妙,令人惊叹,但是有简单,易用的替代方案。如果不是特别严苛的话,基本不会使用。

    关键代码:

    public abstract class Decorator extends BaseClass//这里是神来之笔
    { public BaseClass mBaseClass;//可以传递BaseClass,又可以之后传递Decorator,完成了链头和链条的衔接。
            public Decorator( BaseClass heightBSolider) 
    {
    mBaseClass
    =heightBSolider;
    }
    @Override
    public String showMe()
    {
    return BaseClass.showMe();
    }
    }
    public class Decorator
    {
        //假如我想在showme这个效果上,加点其他效果。第一个想到的便是继承。
        //但是如果效果有上10种。而且排列不同,效果不同,那么继承就基本没办法了。
        //想象3种效果。 单是组合就有3×2种可能。那么就要6个派生类了。这还没有无限叠加效果。
        //当然可以用其他简单方法,直接在类里面加方法,这个类里面的addFire。等方法。简直就是简单到令人发指。
        //但是别忘记了设计模式的原则。 对修改关闭。在一个类中加方法来达到扩展这种做法。比格不高。必须把修改踢到类外部。
        //所以才有了装饰模式。
        //使用不是很常见,因为普通青年,并没有 严苛到 对于很少概率的修改,都把代码提升到设计模式的高度。
    
    
        //简单又高效的类,对于一个战士,想加什么特效自己动手,但是比格不高(没有对修改关闭)
        public class Soldier
        {
            public String showMe()
            {
                return "...";
            }
            public String addFire(String show)
            {
                return "$"+show+"$";
            }
            public String addWater(String show)
            {
                return "~"+show+"~";
            }
            public String addSword(String show)
            {
                return "-"+show+"-";
            }
        }
    
    
    
        public class HeightBSolider
        {
            public String showMe()
            {
                return "...";
            }
        }
    
        //装饰模式,本意是装饰,不改变对象
        //所以,1.必须是输入和输出都是原来的对象。
        //其次,2.一般是对某个方法的复写。
        //所以最直观的是继承。但是不灵活,2中变化,排列要4个类。
        //所以整来整去,装饰类必须继承被装饰类,才能同时满足1,2. 2个条件。
        //而且装饰类必须包含一个被装饰类,这样当装饰类复写方法的时候,不是调用基类的方法,而是调用成员变量的方法。
        //好处在哪里呢?原来固定的多重继承的顺序才能实现的效果,经过包含一个变量,并使用变量的方法来复写。由固定变成了灵活的组合。
        //最终1.装饰类必须继承被装饰类2.构造函数需要传递一个被装饰类,并设置为成员变量。3复写某个需要装饰的方法时,调用类型是被装饰类,而且是自己的成员变量的的方法,
        //来代替基类。
        public class AddFire extends HeightBSolider
        {
            @Override
            public String showMe()
            {
                return "$"+super.showMe()+"$";
            }
        }
    
        public class AddFirePlus extends HeightBSolider
        {
            @Override
            public String showMe()
            {
                return "$"+super.showMe()+"$";
            }
        }
    
        public abstract class ABSDecorator extends HeightBSolider
        {
            public HeightBSolider mHeightBSolider;
            public ABSDecorator(HeightBSolider heightBSolider)
            {
                mHeightBSolider=heightBSolider;
            }
            @Override
            public String showMe()
            {
                return mHeightBSolider.showMe();
            }
        }
    
        public class buff_fire extends ABSDecorator
        {
            public buff_fire(HeightBSolider heightBSolider)
            {
                super(heightBSolider);
            }
    
            public String showMe()
            {
                return "$"+mHeightBSolider.showMe()+"$";
            }
        }
    
        public class buff_Water extends ABSDecorator
        {
            public buff_Water(HeightBSolider heightBSolider)
            {
                super(heightBSolider);
            }
    
            public String showMe()
            {
                return "~"+mHeightBSolider.showMe()+"~";
            }
        }
    
    
        public void Run()
        {
    //        Soldier LeeDragen=new Soldier();
    //        String show=LeeDragen.showMe();
    //        show=LeeDragen.addFire(show);
    //        show=LeeDragen.addWater(show);
    //        LSComponentsHelper.LS_Log.Log_INFO(show);
    
            HeightBSolider Lee=new HeightBSolider();
            Lee=new buff_fire(Lee);
            Lee=new buff_Water(Lee);
            Lee=new buff_Water(Lee);
            Lee=new buff_Water(Lee);
    
            LSComponentsHelper.LS_Log.Log_INFO( Lee.showMe());
    
        }
    }
  • 相关阅读:
    HDU5195 线段树+拓扑
    Codeforces Round #328 (Div. 2)D. Super M 虚树直径
    HDU5489 LIS变形
    BZOJ 1787: [Ahoi2008]Meet 紧急集合 LCA
    Codeforces Round #330 (Div. 2)B. Pasha and Phone 容斥
    Codeforces Round #330 (Div. 2) D. Max and Bike 二分
    Codeforces Round #277 (Div. 2) E. LIS of Sequence DP
    Codeforces Round #277 (Div. 2) D. Valid Sets DP
    内存对齐
    mui列表跳转到详情页优化方案
  • 原文地址:https://www.cnblogs.com/lsfv/p/11136381.html
Copyright © 2020-2023  润新知