(java)从零开始之--装饰者设计模式

装饰者设计模式
简单定义:增强一个类的功能,而且还可以让这些装饰类互相装饰。

应用场景:当要在某个功能的基础上扩充功能,并且扩充的功能具有大量排列组合,通过继承关系会衍生出大量子类,这时候用装饰者模式来解决。

装饰者设计模式的步骤
1. 在装饰类的内部维护一个被装饰类的引用。
2. 让装饰类有一个共同的父类或者是父接口。

例如:人有一种行为叫“吃水果”,其中水果有4种:苹果、香蕉、鸭梨、橘子
现在有需求如下:
A类人行为:吃苹果
B类人行为:先吃苹果,再吃香蕉
C类人行为:先吃香蕉,再吃苹果
D类人行为:先吃橘子,后吃鸭梨

我们先用子类继承来实现:代码如下

 1 interface IEatFruit{
 2 public void eatFruit();
 3 }
 4
 5 class PersonA implements IEatFruit{
 6
 7   @Override
 8   public void eatFruit() {
 9     System.out.println("吃苹果");
10   }
11
12 }
13 class PersonB implements IEatFruit{
14
15 @Override
16   public void eatFruit() {
17     System.out.println("吃苹果");
18     System.out.println("吃香蕉");
19   }
20
21 }
22 class PersonC implements IEatFruit{
23
24   @Override
25   public void eatFruit() {
26     System.out.println("吃香蕉");
27     System.out.println("吃苹果");
28   }
29
30 }
31 class PersonD implements IEatFruit{
32
33   @Override
34   public void eatFruit() {
35     System.out.println("吃橘子");
36     System.out.println("吃鸭梨");
37   }
38
39 }

这样当然是没问题的,每一类人对应new出来的对象 都可以实现对应的需求。
但是,当需求改为:
某类人行为:吃上面四种水果,并且要求有先后顺序
这样的排列组合有24种....
这样你还会用继承去做吗?写24个子类去实现接口,明显不合适。
这时候如果用到装饰者模式,代码则会变成:

  1 interface IEatFruit{
  2     public void eatFruit();
  3 }
  4
  5 class PersonA implements IEatFruit{
  6     IEatFruit eat;
  7     public PersonA(){
  8         this.eat = this;
  9     }
 10     public PersonA(IEatFruit _eat){
 11         this.eat = _eat;
 12     }
 13     @Override
 14     public void eatFruit() {
 15         if(!(this.eat instanceof PersonA)){
 16             this.eat.eatFruit();
 17             System.out.println("吃苹果");
 18         }else{
 19             System.out.println("吃苹果");
 20         }
 21     }
 22
 23 }
 24 class PersonB implements IEatFruit{
 25     IEatFruit eat;
 26     public PersonB(){
 27         this.eat = this;
 28     }
 29     public PersonB(IEatFruit _eat){
 30         this.eat = _eat;
 31     }
 32     @Override
 33     public void eatFruit() {
 34         if(!(this.eat instanceof PersonB)){
 35             this.eat.eatFruit();
 36             System.out.println("吃香蕉");
 37         }else{
 38             System.out.println("吃香蕉");
 39         }
 40     }
 41
 42 }
 43 class PersonC implements IEatFruit{
 44     IEatFruit eat;
 45     public PersonC(){
 46         this.eat = this;
 47     }
 48     public PersonC(IEatFruit _eat){
 49         this.eat = _eat;
 50     }
 51     @Override
 52     public void eatFruit() {
 53         if(!(this.eat instanceof PersonC)){
 54             this.eat.eatFruit();
 55             System.out.println("吃鸭梨");
 56         }else{
 57             System.out.println("吃鸭梨");
 58         }
 59     }
 60
 61 }
 62 class PersonD implements IEatFruit{
 63     IEatFruit eat;
 64     public PersonD(){
 65         this.eat = this;
 66     }
 67     public PersonD(IEatFruit _eat){
 68         this.eat = _eat;
 69     }
 70     @Override
 71     public void eatFruit() {
 72         if(!(this.eat instanceof PersonD)){
 73             this.eat.eatFruit();
 74             System.out.println("吃橘子");
 75         }else{
 76             System.out.println("吃橘子");
 77         }
 78     }
 79
 80 }
 81
 82
 83
 84 public class Demo2 {
 85
 86     public static void main(String[] args) {
 87         //这样就可以通过上述4类人来相互装饰,就可以随意任意一种组合“吃水果”
 88         //如:吃橘子->吃苹果
 89         PersonD d = new PersonD();
 90         PersonA a = new PersonA(d);
 91         a.eatFruit();
 92         System.out.println("-------我是分割线------------");
 93         //如:吃苹果->吃橘子->吃鸭梨->吃香蕉
 94         PersonA a2 = new PersonA();
 95         PersonD d2 = new PersonD(a2);
 96         PersonC c2 = new PersonC(d2);
 97         PersonB b2 = new PersonB(c2);
 98         b2.eatFruit();
 99     }
100
101 }

输出结果如下:
吃橘子
吃苹果
-------我是分割线------------
吃苹果
吃橘子
吃鸭梨
吃香蕉

最后总结
继承实现的增强类和修饰模式实现的增强类有何区别?
继承实现的增强类:
优点:代码结构清晰,而且实现简单.
缺点:对于每一个的需要增强的类都要创建具体的子类来帮助其增强,这样会导致

继承体系过于庞大。
装饰者模式实现的增强类:
优点:内部可以通过多态技术对多个需要增强的类进行增强, 可以使这些装饰类

达到互相装饰的效果。使用比较灵活。
缺点:需要内部通过多态维护需要被增强的类的实例。进而使得代码稍微复杂

时间: 2024-12-15 23:22:29

(java)从零开始之--装饰者设计模式的相关文章

装饰者设计模式

import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; /* 装饰者设计模式:增强一个类的功能,而且还可以让这些装饰类互相装饰. 装饰者设计模式的步骤: 1. 在装饰类的内部维护一个被装饰类的引用. 2. 让装饰类有一个共同的父类或者是父接口. 需求1: 编写一个类拓展BufferedReader的功能, 增强readL

【ThinkingInJava】42、装饰器设计模式

/** * 书本:<Thinking In Java> * 功能:装饰器设计模式 * 装饰器模式使用分层对象来动态透明的向单个对象添加责任.装饰器指定包装在最初的对象周围的所有对象都具有相同的基本接口 * 某些事物是可装饰的,可以通过将其他类包装在这个可装饰对象的四周,来将功能分层. * 装饰器是通过使用组合和形式化结构(可装饰物/装饰器层次结构)来实现的,而混型是基于继承的 * 文件:Decoration.java * 时间:2015年4月21日10:18:43 * 作者:cutter_po

装饰器设计模式初探(Java实现)

本篇随笔主要介绍用Java实现简单的装饰器设计模式: 先来看一下装饰器设计模式的类图:  从图中可以看到,我们可以装饰Component接口的任何实现类,而这些实现类也包括了装饰器本身,装饰器本身也可以再被装饰. 下面是用Java实现的简单的装饰器设计模式,提供的是从基本的加入咖啡入手,可以继续加入牛奶,巧克力,糖的装饰器系统. 1 interface Component { 2 void method(); 3 } 4 class Coffee implements Component { 5

Java学习总结(8)—内存流,打印流,对象流,RandomAccessFile,装饰者设计模式

一.内存流 内存流主要用来操作内存 BytearrayInputStream和ByteArrayOutputStream输入和输出可以把文件作为数据源,也可以把内存作为数据源 (1)ByteArrayInputStream主要完成将内容从内存读入到程序中,而ByteArrayOutputStream的主要功能是是将数据写入到内存中 (2)注意:因为这两个流没有使用系统资源,所以不用关闭,也不需要抛出异常 内存操作示意图 (1)从程序中读:程序<-ByteArrayInputStream<-内存

设计模式--装饰者设计模式(Decorator)

装饰者模式又叫包装模式. 通过另一个对象来扩展自己的行为,在不破坏类的封装的情况下,实现松耦合,易扩展的效果. 抽象组件角色: 一个抽象接口,是被装饰类和装饰类的父接口可以给这些对象动态地添加职责. 具体组件角色:为抽象组件的实现类,是定义了一个具体的对象,也可以给这个对象添加一些职责. 抽象装饰角色:包含一个组件的引用,并定义了与抽象组件一致的接口,继承了Component,从外类来扩展Component类的功能,但对于Component来说,是无需知道Decorator存在的. 具体装饰角色

[设计模式](转)Java中的24种设计模式与7大原则

*:first-child { margin-top: 0 !important; } body > *:last-child { margin-bottom: 0 !important; } a { color: #4183C4; text-decoration: none; } a.absent { color: #cc0000; } a.anchor { display: block; padding-left: 30px; margin-left: -30px; cursor: poin

Java基础之装饰类

------<a href="http://www.itheima.com" target="blank">Java培训.Android培训.ios培训..Net培训</a>.期待与您交流!------ Java基础之装饰类:简介:首先他是一种设计模式属于23种设计模式之一,英文叫Decorator Pattern.又叫装饰者模式.装饰模式是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能.它是通过创建一个包装对象,也就是装饰来

用过滤器和装饰者设计模式(静态代理)解决getParameter乱码问题

post的乱码问题比较好解决,这里主要是对get请求的乱码做处理 解决思路:增强request对象的getParameter方法,使之 getParameter  直接获取到的就是解决乱码后的数据 有四种方式, 1.继承 :(下下策) ①明确知道全类名 可以打印request实现类,可以知道实现类的全类名 ②就是可以在子类中 new 父类 你能确定request实现类,一定可以new么? 确定自己写出的是通用方法.tomcat,weblogic,jboss...... 缺点: ①很难实现,几乎没

装饰器设计模式

通俗的讲装饰器就是在不改变对象结构的前提下,扩充对象的功能. 下面以effective java中例题 问题  我想扩充Hash<set>功能,使得能够统计添加过元素的个数? 或许你可能会自定义一个类通过继承扩展,从而实现计数功能,代码如下: package com.effectJava.Chapter2; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; public class I