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

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

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

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

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

 interface IEatFruit{
public void eatFruit();
} class PersonA implements IEatFruit{   @Override
  public void eatFruit() {
    System.out.println("吃苹果");
  } }
class PersonB implements IEatFruit{ @Override
  public void eatFruit() {
    System.out.println("吃苹果");
    System.out.println("吃香蕉");
  } }
class PersonC implements IEatFruit{   @Override
  public void eatFruit() {
    System.out.println("吃香蕉");
    System.out.println("吃苹果");
  } }
class PersonD implements IEatFruit{   @Override
  public void eatFruit() {
    System.out.println("吃橘子");
    System.out.println("吃鸭梨");
  } }

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

 interface IEatFruit{
public void eatFruit();
} class PersonA implements IEatFruit{
IEatFruit eat;
public PersonA(){
this.eat = this;
}
public PersonA(IEatFruit _eat){
this.eat = _eat;
}
@Override
public void eatFruit() {
if(!(this.eat instanceof PersonA)){
this.eat.eatFruit();
System.out.println("吃苹果");
}else{
System.out.println("吃苹果");
}
} }
class PersonB implements IEatFruit{
IEatFruit eat;
public PersonB(){
this.eat = this;
}
public PersonB(IEatFruit _eat){
this.eat = _eat;
}
@Override
public void eatFruit() {
if(!(this.eat instanceof PersonB)){
this.eat.eatFruit();
System.out.println("吃香蕉");
}else{
System.out.println("吃香蕉");
}
} }
class PersonC implements IEatFruit{
IEatFruit eat;
public PersonC(){
this.eat = this;
}
public PersonC(IEatFruit _eat){
this.eat = _eat;
}
@Override
public void eatFruit() {
if(!(this.eat instanceof PersonC)){
this.eat.eatFruit();
System.out.println("吃鸭梨");
}else{
System.out.println("吃鸭梨");
}
} }
class PersonD implements IEatFruit{
IEatFruit eat;
public PersonD(){
this.eat = this;
}
public PersonD(IEatFruit _eat){
this.eat = _eat;
}
@Override
public void eatFruit() {
if(!(this.eat instanceof PersonD)){
this.eat.eatFruit();
System.out.println("吃橘子");
}else{
System.out.println("吃橘子");
}
} } public class Demo2 { public static void main(String[] args) {
//这样就可以通过上述4类人来相互装饰,就可以随意任意一种组合“吃水果”
//如:吃橘子->吃苹果
PersonD d = new PersonD();
PersonA a = new PersonA(d);
a.eatFruit();
System.out.println("-------我是分割线------------");
//如:吃苹果->吃橘子->吃鸭梨->吃香蕉
PersonA a2 = new PersonA();
PersonD d2 = new PersonD(a2);
PersonC c2 = new PersonC(d2);
PersonB b2 = new PersonB(c2);
b2.eatFruit();
} }

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

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

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

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

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

  1. 装饰器设计模式初探及Java中实际应用举例

    本篇随笔主要介绍用Java实现简单的装饰器设计模式: 先来看一下装饰器设计模式的类图:  从图中可以看到,我们可以装饰Component接口的任何实现类,而这些实现类也包括了装饰器本身,装饰器本身也可 ...

  2. 42、Java装饰者设计模式

    设计模式简介 什么是设计模式?设计模式是可以重复利用的解决方案.软件开发的先驱或者前辈们将之前在开发中遇到的问题进行总结并给出了解决方案,后辈在遇到这些问题之后直接使用这些方案即可解决问题.比如盖高楼 ...

  3. Java的几种常用设计模式

    何为设计模式? 就是对一些常见问题进行归纳总结,并针对具体问题给出一套通用的解决办法(强调的是解决问题的思想): 在开发中,只要遇到这类问题,就可以直接使用这些设计模式解决问题. ---------- ...

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

    post的乱码问题比较好解决,这里主要是对get请求的乱码做处理 解决思路:增强request对象的getParameter方法,使之 getParameter  直接获取到的就是解决乱码后的数据 有 ...

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

    装饰者模式又叫包装模式. 通过另一个对象来扩展自己的行为,在不破坏类的封装的情况下,实现松耦合,易扩展的效果.   抽象组件角色: 一个抽象接口,是被装饰类和装饰类的父接口可以给这些对象动态地添加职责 ...

  6. Java中InputStream装饰器模式的大家族

    本文写在po主初学JAVA时,在学习inputStream摸不着头脑,受Java IO-InputStream家族 -装饰者模式一文启发,所以在理清思路时写下本文.因为初学,如有错误,望指正. 因为和 ...

  7. Java成神路上之设计模式系列教程之一

    Java成神路上之设计模式系列教程之一 千锋-Feri 在Java工程师的日常中,是否遇到过如下问题: Java 中什么叫单例设计模式?请用Java 写出线程安全的单例模式? 什么是设计模式?你是否在 ...

  8. java基础47 装饰着模式设计

    1.装饰者模式 增强一个类的功能,而且还可以让这些装饰类相互装饰 2.装饰者设计模式的步骤 1.在装饰类的内部维护一个被装饰类的引用    2.让装饰者有一个共同的父类或者父接口 3.实例 packa ...

  9. java架构之路-(设计模式)五种创建型模式之单例模式

    设计模式自身一直不是很了解,但其实我们时刻都在使用这些设计模式的,java有23种设计模式和6大原则. 设计模式是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了可 ...

随机推荐

  1. Delphi 编写的Web Service

      一编写服务程序 第一步:File----->New----->Other------>WebServices----->Soap Server Application选择I ...

  2. Linux自定义命令

    linux自定义命令,就是给当前命令取个别名.比如:ls 列出当前的文件,rm + 文件名 就能删除该文件,如何自定义命令,可以使用alias比如:alias gobin='cd /opt/tomca ...

  3. 转 jquery 学习笔记

    jQ通过选择器选择元素,选择器的语法和css类似$(css选择器语法) 参数可以是id.class.tag等等通过如上选择就可以获得一个元素 jQuery名字冲突 解决方法: var jq=jQuer ...

  4. 织梦CMS后台卡死的解决办法

    [复制来于网上]原文地址:http://www.sjyhome.com/dedecms-6.html 改过一次第二次忘记怎么改,还是转一下,下次忘记了翻翻文章就可以知道了.好记忆不如烂笔头 一.原因分 ...

  5. 为什么Android没有iOS那么顺滑

    虽然很多Android手机的配置都比iPhone要高,比如大多数Andorid手机的内存都有1GB,而iPhone 4S只有512MB内存,但用过iPhone的人都知道Android手机在使用的时候总 ...

  6. struts 2学习笔记—浅谈struts的线程安全

    Sruts 2工作流程: Struts 1中所有的Action都只有一个实例,该Action实例会被反复使用.通过上面Struts 2 的工作流程的红色字体部分我们可以清楚看到Struts 2中每个A ...

  7. [置顶] JQuery插件学习教程

    这是JQuery其它常用插件的视频教程,包括validate插件,.comet插件等.同时有大量实例项目,如果你是喜欢JQuery的童鞋千万不要错过. 教程的内容有: 1_validate插件(1) ...

  8. [RxJS] map vs flatMap

    What's the difference between map and flatmap? First, let's show what map is. To show that, I need a ...

  9. MapReduce明星搜索指数统计,找出人气王

    我们继续通过项目强化掌握Combiner和Partitioner优化Hadoop性能 1.项目介绍 本项目我们使用明星搜索指数数据,分别统计出搜索指数最高的男明星和女明星. 2.数据集 3.分析 基于 ...

  10. iOS-你真的会用UIMenuController吗?(详细)

    UIMenuController的介绍 什么是UIMenuController? UIMenuController是UIKit里面的控件 UIMenuController的作用在开发中弹出的菜单栏 后 ...