函数应该做一件事,做好这件事,只做这一件事。

                    ——Clean Code

装饰模式,上代码:

先定义零件类:

 package cn.no3.decorator.template;

 public abstract class Component {

     public abstract void operation();
}

再定义具体零件类(即被装饰类)继承零件类:

 package cn.no3.decorator.template;

 public class ConcreteComponent extends Component{

     @Override
public void operation() {
// TODO Auto-generated method stub
System.out.println("对一个Object进行装饰:");
} }

然后定义装饰类,继承零件类:

 package cn.no3.decorator.template;

 public class Decorator extends Component {

     protected Component component;

     public void setComponent(Component component) {
this.component = component;
} @Override
public void operation() {
//调用的是传入component的operation方法
if (component != null) {
component.operation();
} } }

定义装饰类的子类:

 package cn.no3.decorator.template;

 public class ConcreteDecoratorA extends Decorator {

     private String addedField;

     @Override
public void operation() {
// TODO Auto-generated method stub
super.operation();//第一行调用super,则从前往后包装.反之则从后往前包装
addedField = "新的装饰物A";
System.out.println("装饰了:"+addedField);
}
} public class ConcreteDecoratorB extends Decorator { @Override
public void operation() {
// TODO Auto-generated method stub
super.operation();
AddedBehavior();
} private void AddedBehavior() {
// TODO Auto-generated method stub
System.out.println("完成装饰,最后照个相");
} }

测试类测试:

 package cn.no3.decorator.template;

 public class _Test {

     public static void main(String[] args) {
//新建装饰对象
ConcreteComponent concreteComponent = new ConcreteComponent();
ConcreteDecoratorA concreteDecoratorA = new ConcreteDecoratorA();
ConcreteDecoratorB concreteDecoratorB = new ConcreteDecoratorB();
//逐层包装
//如果注掉下句,还是先调用A的super,发现没传component,于是A的super什么都不做
concreteDecoratorA.setComponent(concreteComponent);//A先调用cC,cC方法不再调用super.
concreteDecoratorB.setComponent(concreteDecoratorA);//B先调用A
//输出最终结果
concreteDecoratorB.operation();
}
}

把这个例子中的Component类换成接口也是一样的:

举个例子:

需求:

定义一个角色,让他实现IWearable接口,

再定义装备实现IWearable接口

人物装备装备.

上代码:

 package cn.no3.decorator.instance;

 public abstract interface IWearable {

     public abstract void operation();
}
 package cn.no3.decorator.instance;

 public class Clothes implements IWearable {

     protected IWearable component;

     public void setComponent(IWearable component) {
this.component = component;
} @Override
public void operation() {
if (component != null) {
component.operation();
} } }
 package cn.no3.decorator.instance;

 //即使只有一双鞋也要定义父类,否则无法通过对象的super.operation对装饰进行传递
public class Shoes implements IWearable { protected IWearable component; public void setComponent(IWearable component) {
this.component = component;
} @Override
public void operation() {
if (component != null) {
component.operation();
}
} }
 package cn.no3.decorator.instance;

 public class Weapons implements IWearable {

     protected IWearable component;

     public void setComponent(IWearable component) {
this.component = component;
} @Override
public void operation() {
if (component != null) {
component.operation();
} } }

他们的子类都是重写父类operation()方法,最先调用(或者最后调用),super.operation();此处省略若干行

 package cn.no3.decorator.instance;

 public class WeaponA extends Weapons {

     @Override
public void operation() {
// TODO Auto-generated method stub
super.operation();
System.out.println("装备了:霜之哀伤");
}
}

角色类

 package cn.no3.decorator.instance;

 public class Character implements IWearable{

     @Override
public void operation() {
// TODO Auto-generated method stub
System.out.println("对一个人物进行装备:");
} }

测试类:

 package cn.no3.decorator.instance;

 public class _Test {

     public static void main(String[] args) {
//新建装备对象
Character concreteComponent = new Character();
ClotheA fantasyKiller = new ClotheA();
ClotheB bravingArmor = new ClotheB();
WeaponA frostmourne = new WeaponA();
WeaponB DoubleRoses = new WeaponB();
ShoesA shoes = new ShoesA();
//逐层包装
fantasyKiller.setComponent(concreteComponent);
bravingArmor.setComponent(fantasyKiller);
frostmourne.setComponent(bravingArmor);
DoubleRoses.setComponent(frostmourne);
shoes.setComponent(DoubleRoses);//shoes.setComponent(shoes)会陷入死循环
//输出最终结果
shoes.operation();
}
}

装饰模式是为已有功能动态地添加更多功能的一种方式

装饰模式把每个要装饰的功能放在单独的类中,并让这个类包装它所需要装饰的对象。因此,当需要执行特殊行为时,客户代码就可以在运行时根据需要有选择地、按顺序地使用装饰功能包装对象了。

装饰功能的核心是:把类中的装饰功能从类中搬出去。

Java学习笔记——设计模式之三.装饰模式的更多相关文章

  1. Java学习笔记——设计模式之五.工厂方法

    水边一只青蛙在笑 --石头和水 工厂方法模式(Factory Method),定义了一个用于创建对象的接口,让实现类决定实例化哪一个类.工厂方法使一个类的实例化延迟到其子类. 这里在简单和工厂的基础上 ...

  2. Java学习笔记——设计模式之二.策略模式

    明确是王道 --Clean Code 先定义策略类 package cn.no2.strategy; public abstract class Strategy { //省略属性 //算法方法 pu ...

  3. Java学习笔记——设计模式之一.简单工厂

    蜀道之难.难于上青天,侧身西望长咨嗟 --蜀道难 设计模式第一篇,简单工厂. 定义Operation类 package cn.no1.simplefactory; public abstract cl ...

  4. Java学习笔记——设计模式之十.观察者模式

     观察者模式(Observer),定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象.这个主题对象在状态发生变化时,会通知所有观察者对象,使他们能够自动更新自己. Subject类: ...

  5. Java学习笔记——设计模式之九.建造者模式

     建造者模式(Builder),将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示. Product类: package cn.happy.design_pattern._09b ...

  6. Java学习笔记-设计模式

    常见设计模式有23种,设计模式是解决某一类问题最行之有效的方法 单例设计模式 解决一个类在内存中只存在一个对象 思想 为了避免其他程序过多建立该类对象.先禁止其他程序建立该类对象 还为了让其他程序可以 ...

  7. Java学习笔记——设计模式之四.代理模式

    To be, or not to be: that is the question. --<哈姆雷特> 代理模式(Proxy),为其他对象提供一种代理以控制对这个对象的访问. 上代码: p ...

  8. Java学习笔记——设计模式之八.外观模式

    外观模式(Facade),为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用. 子系统: package cn.happy.design_patter ...

  9. Java学习笔记——设计模式之七.模板方法模式

    模板方法模式(TemplateMethod),定义一个操作中的算法的骨架,而将一些步骤延迟到子类中.模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤. 结构图: 代码: 算法骨架 ...

随机推荐

  1. JavaScript 简介及语法语句

    JS脚本语言 全称JavaScript:网页里面使用的脚本语言                      非常强大的语言 基础语法 注释语法    单行注释//    多行注释/**/输出语法     ...

  2. require.js 源码解读——配置默认上下文

    首先,我们先来简单说一下,require.js的原理: 1.载入模块
 2.通过模块名解析出模块信息,以及计算出URL
 3.通过创建SCRIPT的形式把模块加载到页面中.
 4.判断被加载的脚本,如 ...

  3. 【C++】浅谈三大特性之一继承(一)

    一,为什么要引入继承? 继承是一个非常自然的概念,现实世界中的许多事物也都是具有继承性的. 例如,爸爸继承爷爷的特性,儿子又继承爸爸的特性等都属于继承的范畴.下面是一个简单的汽车分类图: 在这个分类图 ...

  4. 字符串的模式匹配(Java实现)

    字符串的模式匹配 字串的定位操作通常称做模式匹配,是各种串处理系统中最重要的操作之一.本文主要介绍两种常用的实现算法: 1.暴力匹配 2.KMP算法 1.暴力匹配 时间复杂度为O(n*m):n为主串长 ...

  5. Java基础—JDK环境变量配置

    1.安装JDK 下载网址:http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html 注意点 ...

  6. android 开机自启动实现

    App的开机自启动可以通过注册广播接收器接收开机广播来实现,具体步骤如下: 1.创建 BroadcastReceiver 的派生类,并重写 onReceive() 函数: /** * Created ...

  7. Xcode的Architectures、Valid Architectures和Build Active Architecture Only属性(原创)

    最近xcode升级了5.1版本,升级之后程序报关于要适配arm64机器的错.之前对xcode的参数配置,一直不是很了解,但实现先面对问题了,就调查了一下并解决它. 一个一个来吧. Architectu ...

  8. NOIP2001T4car的旅行计划

    洛谷传送门 一看数据就是floyed(毕竟年代久远),然而建图不是那么好贱好建,只知道三个机场,需要判断斜边来求第4个机场坐标. 往后一些麻烦的建图. 最后floyed就好. --代码 #includ ...

  9. nginx源码编译问题

    [root@localhost nginx-1.7.4]# ./configure checking for OS + Linux 2.6.32-431.el6.x86_64 x86_64 check ...

  10. 解决md5不是windows平台FIPS验证的加密算法的一部分的怪异问题

    一. 发生问题 临近下班时间的下午,领导一句话:项目先上到测试服吧,我明早来看看. 我想项目还没做完,先上到测试服务器,简单看下应该是没什么问题,部署也只是一会儿的事嘛,随后把手头的项目编译,发布,拷 ...