入门设计模式之装饰模式(十)

一、描述

        需要扩展一个类的功能,或给一个类增加附加责任,这些功能可以再动态地撤销。装饰器模式相比生成子类更为灵活,装饰模式是继承的一个替代模式。

二、优劣势


优点:装饰类和被装饰类可以独立发展,不会相互耦合。
缺点:多层装饰比较复杂,顺序特别重要。

三、需求

      QQ形象的展示,主要有个人资料,衣服、裤子、鞋子。


四、不使用设计模式

        都不考虑设计了,直接撸代码

        2个类,

        QQBase.cs  -qq基类  

        NormalQQ.cs --qq实现类

//QQ基类
public abstract class QQBase
{
    public abstract void Show();

}

//QQ对象
public class NormalQQ : QQBase
{
    public string name;
    public int age;

    public NormalQQ(string s,int a)
    {
        name = s;
        age = a;
    }

    public override void Show()
    {
        Debug.Log("姓名:"+name+" "+"年龄:"+age);
        YiFu();
        KuZi();
        XieZi();
    }

    public void YiFu()
    {
        Debug.Log("穿上衣服");
    }

    public void KuZi()
    {
        Debug.Log("穿上裤子");
    }
    public void XieZi()
    {
        Debug.Log("穿上鞋子");
    }
}

//客户端调用
public static void main(string[] args)
{
    QQBase qQ = new NormalQQ("浅伤",18);
    qQ.Show();
}

运行结果

小结:目前的做法是穿衣服、裤子、鞋子的行为写在qq实现类里面,假如我们只需要穿裤子那么Show方法里面的调用是不是得修改了,或者说我想改变下顺序,想先穿裤子然后再鞋子最后在衣服,是不是也得修改Show里面的调用。

 

五、使用设计模式

        通过添加装饰类,把穿物品的行为放在里面,并且装饰类必须也得继承QQBase基类,为了统一Show()接口给客户端调用。       

        6个类,       

        QQBase.cs  -qq基类  

        NormalQQ.cs --qq实现类

        DecoratorBase.cs  --装饰基类

        YiFuDecorator.cs  --装饰衣服类

        KuZiDecorator.cs  --装饰裤子类

        XieZiDecorator.cs --装饰鞋子类

//QQ基类
public abstract class QQBase
{
    public abstract void Show();

}

//QQ对象
public class NormalQQ : QQBase
{
    public string name;
    public int age;

    public NormalQQ(string s,int a)
    {
        name = s;
        age = a;
    }

    public override void Show()
    {
        Debug.Log("姓名:"+name+" "+"年龄:"+age);
    } 
}

//装饰类基类,继承QQBase为了统一Show接口给客户端用
public class DecoratorBase : QQBase
{
    protected QQBase qq;//持有原来的

    //在构造函数里赋值原对象
    public DecoratorBase(QQBase q)
    {
        qq = q;
    }

    public override void Show()
    {
        if (qq!=null)
        {
            qq.Show();//调用下原对象的Show方法,这里对应的是原来输出name和age的作用
        }
    }
}

//衣服装饰类
public class YiFuDecorator : DecoratorBase
{
    public YiFuDecorator(QQBase q):base(q)
    {
       
    }

    public override void Show()
    {         
        base.Show();//调用下原对象的Show方法
        Debug.Log("穿上了衣服");//这里就是我们额外可以添加的功能,这边是穿衣服
    }
}

//裤子装饰类
public class KuZiDecorator : DecoratorBase
{
    public KuZiDecorator(QQBase q) : base(q)
    {

    }

    public override void Show()
    {
        base.Show();//调用下原对象的Show方法
        Debug.Log("穿上了裤子");//这里就是我们额外可以添加的功能,这边是穿裤子
    }
}

//裤子装饰类
public class XieZiDecorator : DecoratorBase
{
    public XieZiDecorator(QQBase q) : base(q)
    {

    }

    public override void Show()
    {
        base.Show();//调用下原对象的Show方法
        Debug.Log("穿上了鞋子");//这里就是我们额外可以添加的功能,这边是穿鞋子
    }
}

//客户端调用
public static void main(string[] args)
{
    QQBase qQ = new NormalQQ("浅伤",18);
    YiFuDecorator yiFuDecorator = new YiFuDecorator(qQ);
    KuZiDecorator kuZiDecorator = new KuZiDecorator(yiFuDecorator);
    XieZiDecorator xieZiDecorator = new XieZiDecorator(kuZiDecorator);

    xieZiDecorator.Show();
}

运行结果

小结:我们通过引入装饰模式,把原来的穿衣服裤子鞋子行为单独从NormalQQ类分离了出来,使得原来的NormalQQ干净了不少,比较装扮衣服这些只是展示的界面才需要用到,所以没必要放NormalQQ里面,我们把每个物品都封装了一个单独的类,并且持有一个上一个对象,所以调用顺序就可以根据自己的需求来赋值了,只需要调用最后使用的装饰类,就会在里面一层一层的往上调用Show()方法,假如我们要调整穿的顺序,在客户端那边调整一下就可以了。

六、设计图

通过学习,我们了解到了装饰模式的应用,我们把刚刚的实现方式画出来。

七、进阶讲解

        装饰模式其实就是适合一些表现上的实现,并且这个表现不是主要核心的功能,我们才可以单独分离出来,比如说手机,它的核心的打电话上网,我们在构造手机类的时候不会把钢化膜、贴子什么的给它也写进去,而是在需要展示它的这些装饰作用的时候才使用装饰类来给它做一个实现 。

八、总结   

觉得有用就留下评论吧^-^

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章