『设计模式』小伙你的穿搭很潮!--装饰者模式

2020-10-28 11:38:29 浏览数 (1)

23种设计模式 额外常用设计模式汇总 (持续更新)

装饰模式(Decorator):又名包装模式。装饰模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案。 装饰模式常常被称为包裹模式,就是因为每一个具体装饰类都将下一个具体装饰类或者具体构成类包裹起来。

包含角色

  • 抽象构成(Component)角色 给出一个抽象接口,以规范准备接收附加责任的对象。
  • 具体构成(Concrete Component)角色 实现组件对象接口,通常就是被装饰器装饰的对象。
  • 装饰(Decorator)角色 持有一个构件(Component)对象的实例,并定义一个与抽象构件接口一致的接口。
  • 具体装饰(Concrete Decorator)角色 负责给构件对象“贴上”附加的责任

特点

  • 装饰模式为对象添加额外责任的方式就像做蛋糕一样,一圈一圈的加上去,中间的面包是核心,是被装饰的对象,是核心任务,外围的都是装饰对象。
  • 这就是说装饰模式包含两部分内容,即装饰独享和被装饰对象。
  • 按照GOF的说法,Decorator模式的意图是:动态的给一个对象添加一些额外的职责。就增加功能来说,Decorator模式相比生成子类更为灵活。
  • 这个被装饰的对象不一定是最原始的那个对象,也可能是被其他装饰器装饰过的对象,反正都是实现的同一接口,也就是同一类型。
  • Decorator模式的效果是:让我们可以创建以decorator对象——负责新的功能的对象——开始的一条对象“链”,并接受与租出的对象。

Decorator链

代码语言:javascript复制
Decorator1->Decorator2->Decorator3->Concrete Comp

模式讲解

功能 能够实现动态地为对象添加功能,是从一个对象外部来给对象增加功能,相当一是改变了对象的外观

对象组合 Favor Composition Over Inheritance

装饰器和组件类的关系 装饰器是用来装饰组件类的关系,装饰器一定要实现和组件类一致的接口,保证他们是同一个类型,并且具有同一个外观这样组合完成的装饰才能够递归调用下去。

本质 动态是手段,组合是目的

优点

  • 装饰模式与集成关系的目的都是要扩展对象的功能,但是装饰模式可以提供比继承更多的灵活性。
  • 通过使用不同的具体装饰类似以及这些装饰类的排列组合,设计师可以创造出很多不同行为的组合。

缺点

会产生很多细粒度对象

装饰模式与策略模式

  • 策略模式改变的是对象的内核
  • 装饰模式改变的是对象的外壳
  • 策略模式是一层调用
  • 装饰模式是递归调用
  • 可以有机结合

装饰模式与AOP

  • APO(Aspect Qriented Programming)是OOP的延续,意思是面向方面编程。
  • 面向对象开发中,烤炉系统的角度通常是纵向的。
  • AOP的主要的功能是:日志记录,性能统计,安全控制,事务处理,异常处理等等。
  • 主要意图是:将日志记录,性能统计,安全控制,事务处理,异常处理等代码从业务员逻辑代码中划分出来,通过对这些行为的分离,我们希望可以将他们独立到非知道业务逻辑的方法中,进而改变这些行业的时候不影响业务逻辑的代码。

举例

实现

代码语言:javascript复制
//抽象构件(Component)角色
public abstract class Component {
    public abstract void operate();
    
//具体构件(ConcreteComponent)角色,被包装对象
public class ConcreteComponent extends Component {
    @Override
    public void operate() {
        System.out.println("ConcreteComponent 原始对象操作");
    }
}
// 装饰(Decorator)角色:
public abstract class Decorator extends Component {
    private Component component;

    /**
     * 构造函数传递要装饰的对象
     * @param component 被装饰的对象
     */
    public Decorator(Component component) {
        this.component = component;
    }

    @Override
    public void operate() {
        //调用被装饰者的方法
        this.component.operate();
    }
}
 
public class ConcreteDecoratorA extends Decorator {

    public ConcreteDecoratorA(Component component) {
        super(component);
    }

    @Override
    public void operate() {
        super.operate();
        //调用自己的方法
        this.operateAMethod();
    }

    private void operateAMethod() {
        System.out.println("ConcreteDecoratorA添加的修饰方法");
    }
}
 
public class ConcreteDecoratorB extends Decorator {

    public ConcreteDecoratorB(Component component) {
        super(component);
    }

    @Override
    public void operate() {
        //调用自己的方法
        this.operateBMethod();
        super.operate();
    }

    private void operateBMethod() {
        System.out.println("ConcreteDecoratorB添加的修饰方法");
    }
}
 
public class Client {

    public static void main(String[] args) {
        //创建原始对象
        Component component = new ConcreteComponent();
        //第一次装饰
        component = new ConcreteDecoratorA(component);
        //第二次装饰
        component = new ConcreteDecoratorB(component);
        //两次装饰后的操作
        component.operate();
    }
}

【问题】 一个人可以搭配不同的服饰:例如,大T恤,垮裤,破球鞋;或者,西装,领带,皮鞋。 【装饰模式实现代码】

代码语言:javascript复制
using System;
namespace Wear
{
    abstract class Component
    {
        public abstract void Show();
    }
    class Person: Component
    {
        private String name;
        public Person() { }
        public Person(String name)
        {
            this.name = name;
        }
        public override void Show()
        {
            Console.WriteLine("装饰的{0}", name);
        }
    }
    class Finery : Component
    {
        protected Component component;
        public Finery(Component component)
        {
            this.component = component;
        }
        public override void Show()
        {
            if(component!=null)
            {
                component.Show();
            }
        }
    }
    class Tshirt:Finery
    {
        public Tshirt(Component component) : base(component) { }
        public override void Show()
        {
            Console.Write("大T恤 ");
            base.Show();
        }
    }
    class BigTrouser : Finery
    {
        public BigTrouser(Component component) : base(component) { }
        public override void Show()
        {
            Console.Write("垮裤 ");
            base.Show();
        }
    }
    class Sneakers : Finery
    {
        public Sneakers(Component component) : base(component) { }
        public override void Show()
        {
            Console.Write("破球鞋 ");
            base.Show();
        }
    }
    class Suit : Finery
    {
        public Suit(Component component) : base(component) { }
        public override void Show()
        {
            Console.Write("西装 ");
            base.Show();
        }
    }
    class Tie : Finery
    {
        public Tie(Component component) : base(component) { }
        public override void Show()
        {
            Console.Write("领带 ");
            base.Show();
        }
    }
    class LeatherShoes : Finery
    {
        public LeatherShoes(Component component) : base(component) { }
        public override void Show()
        {
            Console.Write("皮鞋 ");
            base.Show();
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Person xc = new Person("小菜");
            Console.WriteLine("第一种装扮");
            Finery dtx = new Tshirt(new BigTrouser(new Sneakers(xc)));
            dtx.Show();
            Console.WriteLine("第二种装扮");
            Finery sut = new Suit(new Tie(new LeatherShoes(xc)));
            sut.Show();
        }
    }
}

【UML图】

0 人点赞