`
zddava
  • 浏览: 243678 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

了解设计模式 之 结构模式(四) -- 装饰模式

阅读更多
4. 装饰模式(Decorator Pattern)

装饰模式顾名思义,就是给对象进行一些装饰,让他在原有的基础上动态的添加额外的职责。就好象一个女人,你可以给她"装饰"上漂亮的衣服,做好护肤,买漂亮的首饰然后让他成为一个美女;也可以不给她一顿饱饭,让她天天干活成为黄脸婆,这就是装饰的作用,在原来的基础上附加职责。而不用单独的去定义美女和黄脸婆两个类(世界上的女人那么多种,怎么定义的过来)。通过动态增加职责,可以有效的减少类的数量,还可以使程序的结构更"优雅"。

在Java类库中,IO类就大量的使用了装饰模式,比如说这个语句:

	InputStream is = new BufferedInputStream(new FileInputStream("file"));


这句话就是用了BufferedInputStream去装饰FileInputStream增加了缓冲的功能。

还是延续以前的做法举个现实生活中的例子吧。

比如一个定制生日蛋糕的西饼屋,它的收费方式是这样的:
首先是蛋糕,分为6.8寸,10寸,12寸的等等,分大小来收费,然后加入的奶油和巧克力等等单独收费,为了简单起见,蛋糕的大小的要素就不考虑了,按理说大的蛋糕应该花的奶油的钱要多一些。

下面我们来编码实现这个西饼屋的计费程序。

最初,蛋糕和奶油和巧克力等配料不多,我们的实现是这样的。

首先是蛋糕的基类,它提供了一个抽象方法#price(),这个方法用于返回蛋糕的价格。

	// 蛋糕基类
	public abstract class Cake {
		protected String description;

		public String getDescription() {
			return this.description;
		}

		public abstract float price();

	}


那么一个10寸的巧克力蛋糕就会如下所示的去定义

	public class Chocolate10InchCake extends Cake {

		@Override
		public float price() {
			return 50;
		}

	}


其他种类的蛋糕也可以用相似的方法,但是,很快,程序就遇到了问题,随着西饼屋的蛋糕配料越来越多,我们不得不去创建诸如ChocolateScream10InchCake(10寸巧克力奶油蛋糕),StrawberryScream10InchCake(10寸草莓奶油蛋糕)等等各种各样的子类,另外如果客户希望加入双份的草莓那么要怎么实现呢?这样下去子类的数量会是一个庞大的值,很明显,这种方式绝对不是一个好的设计。

下面,我们就要用装饰模式去改进它了。首先,还是要定义一个蛋糕基类的,这个和之前没什么区别

	// 蛋糕基类
	public abstract class Cake {
		protected String description;

		public String getDescription() {
			return this.description;
		}

		public abstract float price();

	}


然后,定义一个10寸的蛋糕类

	public class TenInchCake extends Cake {

		public TenInchCake() {
			this.description = "10 inch cake";
		}

		@Override
		public float price() {
			return 20;
		}

	}


这个蛋糕单独卖是值20块钱的。

然后,可以定义一系列的配料类,首先定义一个配料基类

	public abstract class CakeDecorator extends Cake {
		protected Cake cake;

		public CakeDecorator() {
			this.description = "cake decorator";
		}
	}


然后各种配料就可以继承自这个类来实现对蛋糕的装饰了。下面是奶油和巧克力的实现:

	public class Scream extends CakeDecorator {

		public Scream(Cake cake) {
			this.cake = cake;
			this.description = this.cake.getDescription() + ", scream";
		}

		@Override
		public float price() {
			return 10 + this.cake.price();
		}

	}

	public class Chocolate extends CakeDecorator {

		public Chocolate(Cake cake) {
			this.cake = cake;
			this.description = this.cake.getDescription() + ", chocolate";
		}

		@Override
		public float price() {
			return 15 + this.cake.price();
		}

	}


同样,也可以用类似的方式实现其他的配料。最后,一个订购巧克力奶油蛋糕和巧克力双份奶油的蛋糕的客户端实现如下:

public class Client {

	public static void main(String[] args) {
		Cake cake1 = new TenInchCake();
		cake1 = new Scream(cake1);
		cake1 = new Chocolate(cake1);

		System.out.println("Desc : " + cake1.getDescription());
		System.out.println("Price: " + cake1.price());

		System.out.println("----------------------------------");
		
		Cake cake2 = new TenInchCake();
		// 双份奶油
		cake2 = new Scream(cake2);
		cake2 = new Scream(cake2);
		cake2 = new Chocolate(cake2);

		System.out.println("Desc : " + cake2.getDescription());
		System.out.println("Price: " + cake2.price());
	}

}


它的运行结果如下:

	Desc : 10 inch cake, scream, chocolate
	Price: 45.0
	----------------------------------
	Desc : 10 inch cake, scream, scream, chocolate
	Price: 55.0


上面描述的就是装饰模式了,它通过动态追加职责的方式有效的解决了"子类爆炸",另外出现需要撤销职责的情况,也可以使用装饰模式,因为这个方法并没有改变原来的对象。

最后给出装饰模式的类图:

  • 大小: 23.8 KB
分享到:
评论

相关推荐

    设计模式专题之(七)装饰模式---设计模式装饰模式示例代码(python--c++)

    装饰模式是一种结构型设计模式,它允许在运行时动态地给对象添加新的行为或职责,同时保持对象的接口不变。这种模式使得我们可以在不修改原有代码的基础上,通过组合不同的装饰来扩展对象的功能,实现了代码的高可...

    JAVA-设计模式-结构型模式-装饰模式

    JAVA-设计模式-结构型模式-装饰模式

    c++设计模式-结构型模式-装饰器模式

    c++设计模式-结构型模式-装饰器模式;QT工程;c++简单源码; 装饰器(Decorator)模式的定义:指在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)的模式,它属于对象结构型模式。

    设计模式--装饰者模式java例子

    装饰者模式是软件设计模式中的一种结构型模式,它的主要目的是动态地给对象添加新的功能,而无需修改原有代码。在Java中,装饰者模式通常通过继承和组合来实现,它提供了一种比继承更灵活的方式来扩展对象的功能。...

    54-Spring设计模式之装饰器模式1

    Spring 设计模式之装饰器模式详解 在软件设计中,经常会遇到需要在不修改原有代码的情况下,添加新的功能或行为。这时,装饰器模式便可以发挥其作用。在 Spring 设计模式中,装饰器模式是非常重要的一种设计模式。 ...

    HeadFirst 设计模式学习笔记3--装饰模式 Demo

    装饰模式是一种结构型设计模式,它允许在运行时向对象添加新的行为或责任,而无需修改对象的源代码。这种模式通常用于保持对象的原始类结构不变,同时增强其功能。HeadFirst 设计模式系列书籍以其生动有趣的插图和...

    软件设计模式与体系结构期末课程大作业-服装管理系统

    在软件开发领域,设计模式和体系结构是两个至关重要的概念,尤其在大型项目中,它们对于软件的可维护性、可扩展性和可复用性起着决定性的作用。本项目——“服装管理系统”是一个很好的实践案例,让我们深入探讨其中...

    23个设计模式之一的装饰ppt-java-极客学院

    装饰模式是一种结构型设计模式,它允许我们向一个对象动态地添加新的行为或属性,而无需修改原有对象的代码。这种模式在Java等面向对象语言中广泛应用,因为它提供了对类扩展的一种灵活方式,避免了使用继承带来的...

    软件设计模式与体系结构课后习题代码(孙玉山).zip

    在软件开发领域,设计模式和体系结构是至关重要的概念,它们是解决常见问题的模板,为软件的可扩展性、可维护性和可重用性提供了基础。本资源"软件设计模式与体系结构课后习题代码(孙玉山).zip"包含了孙玉山教授讲解...

    设计模式课件大全

    设计模式07-组合模式、装饰模式 设计模式09-外观模式、享元模式 设计模式10-代理模式、结构型模式大复习 设计模式11-行为模式-责任链、命令模式 设计模式12-解释器模式 设计模式13-迭代器模式 设计模式14-中介者模式...

    GOF-设计模式-Design Patterns-英文原版-高清-有目录-有页码

    #### 四、设计模式目录组织 **设计模式目录的组织结构:** 设计模式通常按照其解决的设计问题类型进行分类。本书将其分为三大类: 1. **创建型模式**(Creational Patterns) 2. **结构型模式**(Structural Patterns)...

    软件体系结构设计模式作业

    在IT行业中,软件体系结构设计模式是开发高质量、可维护和可扩展的软件系统的关键要素。设计模式是一种在特定上下文中解决常见问题的最佳实践,它为软件设计提供了可重用的解决方案。本作业将深入探讨软件体系结构...

    设计模式之美——教你写出高质量代码

    "设计模式之美——教你写出高质量代码"这个主题旨在帮助开发者更好地理解和应用设计模式,从而提升代码的质量和可维护性。设计模式不仅对面试有所帮助,也是职场发展中的必备技能,无论你使用哪种开发语言。 设计...

    设计模式之结构型模式

    在本文中,我们将深入探讨结构型设计模式,特别是桥接模式、适配器模式、装饰者模式和组合模式,以及它们在实际场景中的应用。 1. **桥接模式**: 桥接模式将抽象部分与实现部分分离,使得它们可以独立进行变化。...

    设计模式精解-GoF-23种设计模式解析--附C++源代码

    这些模式是由Erich Gamma、Richard Helm、Ralph Johnson和John Vlissides四位大师,通常被称为GoF(Gang of Four),在他们的经典著作《设计模式:可复用面向对象软件的基础》中提出的。这本书详细阐述了23种设计...

    C#设计模式之Decorator 装饰模式

    装饰模式(Decorator Pattern)是设计模式中的一种结构型模式,它在不改变原有对象的基础上,通过添加额外的职责来扩展对象的功能。在C#中,装饰模式尤其适用于那些需要动态地增加或减少对象功能的情况,避免了使用...

    设计模式 - 装饰模式(C++实例)

    装饰模式是一种结构型设计模式,它允许在运行时向对象添加新的行为或责任,而无需修改对象的源代码。这种模式在软件工程中非常常见,因为它提供了灵活性,使得我们可以独立于对象的组合来扩展功能。 在C++中,装饰...

    设计模式之装饰模式

    1. **装饰模式的基本结构**:装饰模式通常包括四个角色:抽象组件(Component)接口,具体组件(Concrete Component)类,抽象装饰(Decorator)类以及具体装饰(Concrete Decorator)类。抽象组件定义了对象的基本...

    设计模式之装饰者模式-极客学院

    装饰者模式是面向对象设计中的一种结构型模式,它的主要目的是动态地给一个对象添加一些额外的职责,即增加功能,同时又不破坏原有的结构。装饰者模式是一种比继承更灵活的扩展对象行为的方式,它避免了类爆炸问题,...

    软件设计模式与体系结构孙云山课后习题234章答案.zip

    孙云山老师的“软件设计模式与体系结构”课程深入探讨了这些模式及其在构建复杂系统中的应用。本资料集合包含了课后习题的第234章答案,这将有助于学生深化对设计模式的理解,并提升其实际应用能力。 设计模式是...

Global site tag (gtag.js) - Google Analytics