设计模式笔记——装饰模式

装饰模式

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

1.装饰模式的特点

(1)装饰对象和真实对象有相同的接口。这样客户端对象就能以和真实对象相同的方式和装饰对象交互。

(2)装饰对象包含一个真实对象的引用(reference)

(3)装饰对象接受所有来自客户端的请求。它把这些请求转发给真实的对象。

(4)装饰对象可以在转发这些请求以前或以后增加一些附加功能。这样就确保了在运行时,不用修改给定对象的结构就可以在外部增加附加的功能。在面向对象的设计中,通常是通过继承来实现对给定类的功能扩展。

2.适用性

(1)需要扩展一个类的功能,或给一个类添加附加职责。

(2)需要动态的给一个对象添加功能,这些功能可以再动态的撤销。

(3)需要增加由一些基本功能的排列组合而产生的非常大量的功能,从而使继承关系变的不现实。

(4)当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。

所有设计模式总结请参考:http://blog.csdn.net/chr23899/article/details/46999267

所有设计原则总结请参考:http://blog.csdn.net/chr23899/article/details/46999401

首先来看下具体的效果图

从效果图中我们可以看出用户在生成草原时可以用八中选择: 不装饰、太阳、白云、小花、太阳+白云、太阳+小花、白云+小花、全装饰。如果采用创建子类的方式,则需要七个子类来完成相应的功能,这就会出现’子类爆炸’的现象。如果装饰模式则可以动态的添加装饰而避免此类现象的发生。

先看下具体的装饰类图效果

类的详细设计代码如下:

//定义草原抽象类
    public abstract class GrassLand
    {
        //抽象方法 用于重写
        public abstract void draw(PictureBox pic, Graphics g);
    }

    //定义初始子类LandModel
    public class LandModel : GrassLand
    {
        //实现抽象函数
        public override void draw(PictureBox picbox_img, Graphics g)
        {
            //蓝天
            g.FillRectangle(Brushes.Blue, 0, 0, picbox_img.Width, picbox_img.Height);
            //绿草
            g.FillPie(Brushes.Green, 0, picbox_img.Height / 4 * 3, picbox_img.Width * 2, picbox_img.Height / 2, 180, 270);
        }
    }

    //定义装饰者类
    public class Decorator : GrassLand
    {
        //定义草场对象
        private GrassLand land;

        //构造函数赋初值
        public Decorator(GrassLand l)
        {
            land = l;
        }

        //重写draw方法
        public override void draw(PictureBox pic, Graphics g)
        {
            if (land != null)
                land.draw(pic, g);
        }
    }

    //绘制太阳
    public class DrawSun : Decorator
    {
        public DrawSun(GrassLand land)
            : base(land)
        {
        }

        public override void draw(PictureBox pic, Graphics g)
        {
            base.draw(pic, g);
            addsun(pic, g);
        }

        //完成要装饰的内容
        private void addsun(PictureBox picbox_img, Graphics g)
        {
            //太阳
            g.FillEllipse(Brushes.Red, picbox_img.Width / 8, picbox_img.Height / 8, picbox_img.Width / 7, picbox_img.Width / 7);
        }
    }

    //绘制白云
    public class DrawCloud : Decorator
    {
        public DrawCloud(GrassLand land)
            : base(land)
        {
        }

        public override void draw(PictureBox pic, Graphics g)
        {
            base.draw(pic, g);
            addcloud(pic, g);
        }

        //完成要装饰的内容
        private void addcloud(PictureBox picbox_img, Graphics g)
        {
            //白云
            g.FillEllipse(Brushes.GhostWhite, picbox_img.Width / 8 * 3, picbox_img.Height / 6, picbox_img.Width / 7, picbox_img.Height / 9);
            g.FillEllipse(Brushes.GhostWhite, picbox_img.Width / 8 * 6, picbox_img.Height / 6, picbox_img.Width / 7, picbox_img.Height / 9);
            g.FillEllipse(Brushes.GhostWhite, picbox_img.Width / 16 * 9, picbox_img.Height / 4, picbox_img.Width / 7, picbox_img.Height / 9);
        }
    }

    public class DrawFlower : Decorator
    {
        public DrawFlower(GrassLand land)
            : base(land)
        {
        }

        public override void draw(PictureBox pic, Graphics g)
        {
            base.draw(pic, g);
            addflower(pic, g);
        }

        //完成要装饰的内容
        private void addflower(PictureBox picbox_img, Graphics g)
        {
            //小花
            g.FillEllipse(Brushes.Pink, picbox_img.Width / 9, picbox_img.Height - 10, 10, 8);
            g.FillEllipse(Brushes.Pink, picbox_img.Width / 7, picbox_img.Height - 20, 10, 8);
            g.FillEllipse(Brushes.Pink, picbox_img.Width / 5, picbox_img.Height - 30, 10, 8);
            g.FillEllipse(Brushes.Pink, picbox_img.Width / 3, picbox_img.Height - 28, 10, 8);
            g.FillEllipse(Brushes.Pink, picbox_img.Width / 16 * 15, picbox_img.Height - 45, 10, 8);
            g.FillEllipse(Brushes.Pink, picbox_img.Width / 16 * 13, picbox_img.Height - 58, 10, 8);
            g.FillEllipse(Brushes.Pink, picbox_img.Width / 16 * 11, picbox_img.Height - 15, 10, 8);
            g.FillEllipse(Brushes.Pink, picbox_img.Width / 16 * 9, picbox_img.Height - 27, 10, 8);
            g.FillEllipse(Brushes.Pink, picbox_img.Width / 16 * 7, picbox_img.Height - 39, 10, 8);
        }
    }

3.在装饰者模式中各个角色有:

(1)抽象构件(GrassLand)角色: 给出一个抽象接口,以规范准备接受附加责任的对象。

(2)具体构件(LandModel)角色: 定义一个将要接收附加责任的类。

(3)装饰(Decorator)角色: 持有一个构件(GrassLand)对象的实例,并定义一个与抽象构件接口一致的接口。

(4)具体装饰(DrawSun、DrawCloud和DrawFlower)角色: 负责给构件对象 ”贴上“附加的责任。

4.装饰模式的优点:

(1)Decorator模式与继承关系的目的都是要扩展对象的功能,但是Decorator可以提供比继承更多的灵活性。

(2)通过使用不同的具体装饰类以及这些装饰类的排列组合,设计师可以创造出很多不同行为的组合。

源程序下载地址:http://download.csdn.net/detail/chr23899/8925611

原文出处:http://blog.csdn.net/chr23899 转发请说明

版权声明:本文为博主原创文章,未经博主允许不得转载。 博客列表: http://blog.csdn.net/chr23899

时间: 2024-08-25 15:42:35

设计模式笔记——装饰模式的相关文章

大话设计模式笔记 装饰模式

装饰模式(Decorator),动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活. package decoratePattern; public abstract class Component { public abstract void Operation(); } package decoratePattern; public class ConcreteComponent extends Component { @Override public void

设计模式 笔记 装饰模式 Decorator

//---------------------------15/04/17---------------------------- //Decorator 装饰模式----对象结构型模式 /* 1:意图: 动态地给一个对象添加额外的职业,就增加功能来说,Decorator模式相比生成子类更为灵活. 2:别名: 包装器(Wrapper) 3:动机: 4:适用性: 1>在不影响其他对象的情况下,以动态.透明的方式给单个对象添加职责. 2>处理那些可以撤销的职责. 3>当不能采用生成子类的方法

跟我学设计模式视频教程——装饰模式,装饰模式VS代理模式

课程视频 装饰模式 装饰模式VS代理模式1 装饰模式VS代理模式2 课程笔记 课程笔记 课程代码 课程代码 新课程火热报名中 课程介绍 跟我学设计模式视频教程--装饰模式,装饰模式VS代理模式,布布扣,bubuko.com

(CZ深入浅出Java基础)设计模式笔记

一.面向对象思想设计原则 1.单一职责原则 其实就是开发人员经常说的"高内聚,低耦合",也就是说,每个类应该只有一个职责,对外只能提供一种功能,而引起类变化的原因应该只有一个.在设计模式中,所有的设计模式都遵循这一原则. 2.开闭原则 核心思想是:一个对象对扩展开放,对修改关闭.其实开闭原则的意思就是:对类的改动是通过增加代码进行的,而不是修改现有代码.也就是说软件开发人员一旦写出了可以运行的代码,就不应该去改动它,而是要保证它能一直运行下去,如何能够做到这一点呢?这就需要借助于抽象和

[设计模式] .NET设计模式笔记 - 有多少种设计模式

.NET下的23中设计模式. ※创建型模式篇 ●单件模式(Single Pattern) ●抽象工厂模式(Abstract Factory) ●建造者模式(Builder Pattern) ●工厂方法(Factory Method) ●原型模式(Protype Pattern) ※结构型模式篇 ●适配器模式(Adapter Pattern) ●桥接模式(Bridge Pattern) ●装饰模式(Decorator Pattern) ●组合模式(Composite Pattern) ●外观模式(

JAVA设计模式之 装饰模式【Decorator Pattern】

一.概述 动态地给一个对象增加一些额外的职责,就增加对象功能来说,装饰模式比生成子类实现更为灵活.装饰模式是一种对象结构型模式.装饰模式是一种用于替代继承的技术,使用对象之间的关联关系取代类之间的继承关系.在装饰模式中引入了装饰类,在装饰类中既可以调用待装饰的原有类的方法,还可以增加新的方法,以扩充原有类的功能. 二.适用场景 装饰原有对象.在不改变原有对象的情况下扩展增强新功能/新特征..当不能采用继承的方式对系统进行扩展或者采用继承不利于系统扩展和维护时可以使用装饰模式. 三.UML类图 四

php设计模式笔记:单例模式

意图: 保证一个类仅有一个实例,并且提供一个全局访问点 单例模式有三个特点: 1.一个类只有一个实例2.它必须自行创建这个实例3.必须自行向整个系统提供这个实例 主要实现: Singleton定义了一个instance操作,允许外部访问它的唯一实例,instance是一个类方法,负责创建它的唯一实例. singleton适用场景: 1.当类只能有一个实例而且外部可以从一个公共的访问点访问它.2.当这个唯一实例应该是通过子类化可扩展的.并且用户应该无需更改代码就能使用一个扩展的实例时. Singl

Asp.net设计模式笔记之一:理解设计模式

GOF设计模式著作中的23种设计模式可以分成三组:创建型(Creational),结构型(Structural),行为型(Behavioral).下面来做详细的剖析. 创建型 创建型模式处理对象构造和引用.他们将对象实例的实例化责任从客户代码中抽象出来,从而让代码保持松散耦合,将创建复杂对象的责任放在一个地方,这遵循了单一责任原则和分离关注点原则. 下面是“创建型”分组中的模式: 1.Abstract Factory(抽象工厂)模式:提供一个接口来创建一组相关的对象. 2.Factory Met

设计模式----看大话设计模式笔记(二)

9.原型模式(Prototype): 用原型实例指定创建对象的种类,并通过拷贝这些原型创建行的对象. UML图: 原型模式其实就是从一个对象创建另一个可定制的对象,并且不需要知道任何创建的细节. .NET 中实现ICloneable接口即可. 一般在初始化信息不发生变化的情况下,克隆是最好的办法,隐藏了对象创建的细节,又提高了性能. MemberwiseClone()方法,如果字段是值类型,对该字段进行逐位复制:如果是引用类型,复制引用但是不复制引用的对象,因此原始对象及产生的副本引用同一对象.