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


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

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

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

先不要装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());

    }
}

优质内容筛选与推荐>>
1、有道难题
2、ps-抠图
3、LeetCode:154. 寻找旋转排序数组中的最小值 II
4、oracle小知识点总结
5、What is Thread


长按二维码向我转账

受苹果公司新规定影响,微信 iOS 版的赞赏功能被关闭,可通过二维码转账支持公众号。

    阅读
    好看
    已推荐到看一看
    你的朋友可以在“发现”-“看一看”看到你认为好看的文章。
    已取消,“好看”想法已同步删除
    已推荐到看一看 和朋友分享想法
    最多200字,当前共 发送

    已发送

    朋友将在看一看看到

    确定
    分享你的想法...
    取消

    分享想法到看一看

    确定
    最多200字,当前共

    发送中

    网络异常,请稍后重试

    微信扫一扫
    关注该公众号





    联系我们

    欢迎来到TinyMind。

    关于TinyMind的内容或商务合作、网站建议,举报不良信息等均可联系我们。

    TinyMind客服邮箱:support@tinymind.net.cn