Java学习笔记——设计模式之三.装饰模式
函数应该做一件事,做好这件事,只做这一件事。
——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学习笔记——设计模式之三.装饰模式的更多相关文章
- Java学习笔记——设计模式之五.工厂方法
		水边一只青蛙在笑 --石头和水 工厂方法模式(Factory Method),定义了一个用于创建对象的接口,让实现类决定实例化哪一个类.工厂方法使一个类的实例化延迟到其子类. 这里在简单和工厂的基础上 ... 
- Java学习笔记——设计模式之二.策略模式
		明确是王道 --Clean Code 先定义策略类 package cn.no2.strategy; public abstract class Strategy { //省略属性 //算法方法 pu ... 
- Java学习笔记——设计模式之一.简单工厂
		蜀道之难.难于上青天,侧身西望长咨嗟 --蜀道难 设计模式第一篇,简单工厂. 定义Operation类 package cn.no1.simplefactory; public abstract cl ... 
- Java学习笔记——设计模式之十.观察者模式
		观察者模式(Observer),定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象.这个主题对象在状态发生变化时,会通知所有观察者对象,使他们能够自动更新自己. Subject类: ... 
- Java学习笔记——设计模式之九.建造者模式
		建造者模式(Builder),将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示. Product类: package cn.happy.design_pattern._09b ... 
- Java学习笔记-设计模式
		常见设计模式有23种,设计模式是解决某一类问题最行之有效的方法 单例设计模式 解决一个类在内存中只存在一个对象 思想 为了避免其他程序过多建立该类对象.先禁止其他程序建立该类对象 还为了让其他程序可以 ... 
- Java学习笔记——设计模式之四.代理模式
		To be, or not to be: that is the question. --<哈姆雷特> 代理模式(Proxy),为其他对象提供一种代理以控制对这个对象的访问. 上代码: p ... 
- Java学习笔记——设计模式之八.外观模式
		外观模式(Facade),为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用. 子系统: package cn.happy.design_patter ... 
- Java学习笔记——设计模式之七.模板方法模式
		模板方法模式(TemplateMethod),定义一个操作中的算法的骨架,而将一些步骤延迟到子类中.模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤. 结构图: 代码: 算法骨架 ... 
随机推荐
- Spark2.1.0分布式集群安装
			一.依赖文件安装 1.1 JDK 参见博文:http://www.cnblogs.com/liugh/p/6623530.html 1.2 Hadoop 参见博文:http://www.cnblogs ... 
- Linux系统date命令的参数及获取时间戳的方法
			date指令相关用法示例 date 用法: date [OPTION]... [+FORMAT]date [-u|--utc|--universal] [MMDDhhmm[[CC]YY][.ss]] ... 
- 【Egret】Native版本 视频播放器(android)
			前段时间,领导说客户要一个平板版本的视频播放器,把我们做的一些视频资源放进去,要是本地的:我们部门又没有app开发程序员,正好又前段我在实验egret的app打包功能,就说用egret做(ps:本来想 ... 
- 手机自动化测试:Appium代码之Logger
			手机自动化测试:Appium代码之Logger poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.poptest推出手机自动化测 ... 
- Android开发 旋转屏幕导致Activity重建解决方法(转)
			文章来源:http://www.jb51.net/article/31833.htm Android开发文档上专门有一小节解释这个问题.简单来说,Activity是负责与用户交互的最主要机制,任何“ ... 
- Android -- Annotation(注解)原理详解及常见框架应用
			1,我们在上一篇讲到了EventBus源码及3.0版本的简单使用,知道了我们3.0版本是使用注解方式标记事件响应方法的,这里我们就有一个疑问了,为什么在一个方法加上类似于"@Subscrib ... 
- nginx学习笔记——http module分析
			源码:nginx 1.12.0 nginx由于其高性能.扩充性好等特点在迅速走红,越来越多的公司采用nginx作web服务器.负载均衡.waf等 工作,一些基于nginx ... 
- 为部署ASP.NET Core准备:使用Hyper-V安装Ubuntu Server 16.10
			概述 Hyper-V是微软的一款虚拟化产品,和VMWare一样采用的hypervisor技术.它已经被内嵌到Win10系统内,我们只需要进行简单的安装即可.但是前提是要确保你的机器已经启用虚拟化,可以 ... 
- Linux配置tomcat (centos配置java环境  tomcat配置篇  总结三)
			♣下载安装tomcat7 ♣设置启动和关闭 ♣设置用户名和密码 ♣发布java web项目 声明:这篇教程是建立在前两篇教程的基础上的,所以,还没安装工具和jdk,可以先看这个系列的前面两篇(去到文末 ... 
- 【转】JDBC学习笔记(9)——DBUtils的使用
			转自:http://www.cnblogs.com/ysw-go/ 使用DBUtils提供的功能需要使用commons-dbutils-1.6.jar这个JAR包,在Apache官网可以下载到 使用D ... 
