设计模式:十.装饰模式

本文介绍了装饰模式的概念、使用场景及其实现方式。装饰模式允许在不修改原有类的基础上为其添加新的功能,通过组合的方式实现了功能的扩展,适用于动态扩展类的功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

装饰模式(Decorator Mode):是结构模式的一种,它又与代理模式差不多,只不过装饰模式装饰类里关联的是自己的父类。并且可以多层嵌套。把所需的功能按正确的顺序串联起来进行控制。装饰模式利用关联自己的父类来对对象进行封装。这样每个子类装饰对象只关心自己的功能,不需要关心如何被添加到对象链当中。


目录

1. 意图:

想要动态的扩展一个类。动态添加,动态撤销。

定义:动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。

2. 如何使用:

何时使用:1.扩展一个类的功能。
2.动态增加功能,动态撤销。

如何解决:在不增加很多子类的情况下扩展类,将具体功能职责划分,同时继承装饰器类。

优点:装饰类和被装饰类可以独立发展,不会相互耦合。装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。

缺点:多层装饰比较复杂。

3. UML模板:

image

4. 关键代码:


public class DecoratorMode : MonoBehaviour
{
    void Start()
    {
        ConcreteComponent concrete = new ConcreteComponent();
        ConcreteDecoratorA concreteA = new ConcreteDecoratorA();
        ConcreteDecoratorB concreteB = new ConcreteDecoratorB();
        //装饰的方法是:首先用ConcreteComponent实例化对象C,然后用ConcreteDecoratorA
        //的实例化对象d1来包装c,再用ConcreteDecoratorB的对象d2包装d1,最终执行d2的Operation()
        concreteA.SetComponent(concrete);
        concreteB.SetComponent(concreteA);
        concreteB.Operation();

    }
}
//定义一个对象接口,可以给这些对象动态的添加职责
public abstract class Component
{
    public abstract void Operation();
}
public  class ConcreteComponent : Component
{
    public override void Operation()
    {
        Debug.Log("具体对象的操作");
    }
}
public abstract class Decorator : Component
{
    protected Component component;
    public void SetComponent(Component component)//设置Componet
    {
        this.component = component;
    }
    public override void Operation()
    {
        if (component!=null)
        {
            component.Operation();
        }
    }
}
public class ConcreteDecoratorA : Decorator
{
    private string addedState;//本类的独有功能,以区别于ConcreteDecoratorB
    public override void Operation()
    {
        //首先运行原Ccomponent的Operation(),在执行本类的功能,如addedState,相当于对原Component进行了装饰
        base.Operation();
        addedState = "New State";
        Debug.Log("具体装饰对象A的操作"+ addedState);
    }
}
public class ConcreteDecoratorB : Decorator
{
    public override void Operation()
    {
        //首先运行原Component的Operation(),在执行本类的功能,如AddedBehavior(),相当于对原Component进行了装饰。
        base.Operation();
        AddedBehavior();
        Debug.Log("具体装饰对象B的操作");
    }
    //本类独有的方法,以区别于ConreteDecoratorB
    private void AddedBehavior()
    {
        Debug.Log("AddedBehavior");
    }
}

5. 实例:

UML图
image
代码


public class DecoratorModeDemo:MonoBehaviour
{
    private void Start()
    {
        Person xc = new Person("小菜");
        Debug.Log("\n第一种装扮:");
        TShirts ts = new TShirts();
        BigTrouser kuanku = new BigTrouser();
        Necktie lingdai = new Necktie();
        Leathershoes pixie = new Leathershoes();
        Gymshoes qiuxie = new Gymshoes();
        Jacket xizhuang = new Jacket();
        kuanku.Decorate(xc);
        lingdai.Decorate(kuanku);
        pixie.Decorate(lingdai);
        pixie.Show();
        //Debug.Log("\n第二种装扮");
        //pixie.Decorate(xc);
        //qiuxie.Decorate(pixie);
        //xizhuang.Decorate(qiuxie);
        //xizhuang.Show();
    }
}
public class Person
{
    public Person() { }

    private string name;
    public Person(string name)
    {
        this.name = name;
    }
    public virtual void Show()
    {
        Debug.LogFormat("装扮的{0}",name);
    }
}
public class Finery : Person
{
    protected Person component;
    //打扮
    public void Decorate(Person component)
    {
        this.component = component;
    }
    public override void Show()
    {
        if (component != null)
        {
            component.Show();
        }
    }
}
public class TShirts : Finery
{
    public override void Show()
    {
        base.Show();
        Debug.Log("大T恤");

    }
}
public class BigTrouser : Finery
{
    public override void Show()
    {
        base.Show();
        Debug.Log("垮裤");

    }
}
public class Necktie : Finery
{
    public override void Show()
    {
        base.Show();
        Debug.Log("领带");

    }
}
public class Leathershoes : Finery
{
    public override void Show()
    {
        base.Show();
        Debug.Log("皮鞋");

    }
}
public class Gymshoes : Finery
{
    public override void Show()
    {
        base.Show();
        Debug.Log("球鞋");

    }
}
public class Jacket:Finery
{
    public override void Show()
    {
        base.Show();
        Debug.Log("西装");

    }
}

最后这个例子很有意思,base.Show()在控制台输出Debug.Log(“”)的下面。这样输出的时候是从后往前的。比如说你先西装,皮鞋,最后T恤。最后输出的是T恤皮鞋西装。反之,如我这样写则是正向输出。这里写要注意,一不注意很容易死循环的23333.
这里我们跟一下代码:

        kuanku.Decorate(xc);
        lingdai.Decorate(kuanku);
        pixie.Decorate(lingdai);
        pixie.Show();

最后我们执行的是皮鞋的show方法。我们把父方法带过来

public override void Show()
    {
        if (lingdai != null)
        {
            lingdai.Show();
        }
       // base.Show();
        Debug.Log("皮鞋");
    }

我们在把领带里面的show方法带进来

public override void Show()
    {
        if (lingdai != null)
        {
            //base.Show();
            if(kuaku!=null)
            {
                kuaku.show();
            }
            Debug.log("领带");
            ////lingdai.Show();
        }
       // base.Show();
        Debug.Log("皮鞋");
    }

如上我们把pixie.Show()方法完整的展现出来

public override void Show()
    {
        if (lingdai != null)
        {
            if(kuaku!=null)
            {
                if(xc!=null)
                {
                   xc.Show();
                }
                debug.log("垮裤");
            }
            Debug.log("领带");

        }
        Debug.Log("皮鞋");
    }

执行顺序是xc,垮裤,领带,皮鞋。那如果代码是这样呢

public override void Show()
    {
        Debug.Log("西装");
        base.Show();
    }

如上我们把pixie.Show()方法完整的展现出来

public override void Show()
    {
      Debug.Log("皮鞋");
        if (lingdai != null)
        {
          Debug.log("领带");
            if(kuaku!=null)
            {
              debug.log("垮裤");
                if(xc!=null)
                {
                   xc.Show();
                }

            }
        }
    }

执行顺序是皮鞋,领带,垮裤,xc。
是不是很有趣呢。我们挖到了装饰模式的精髓。但是还是那句话,小心死循环。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值