一、装饰模式(decorator)

职责:动态的为一个对象增加新的功能。

是一种用于代替继承的技术,无须通过继承增加子类就能扩展对象的新功能。使用对象的关联关系代替继承关系,更加灵活,避免类体系的膨胀。

实现细节:

– Component抽象构件角色:真实对象和装饰对象有相同的接口。这样,客户端对象就能够以与真实对象相同的方式同装饰对象交互。

– ConcreteComponent 具体构件角色(真实对象):IO流中的FileInputStream、FileOutputStream

– Decorator装饰角色:持有一个抽象构件的引用。装饰对象接受所有客户端的请求,并把这些请求转发给真实的对象,这样,就能在真实对象调用前后增加新的功能。

– ConcreteDecorator具体装饰角色:负责给构件对象增加新的责任。

【被装饰对象与装饰对象】

/***
* 抽象组件ICar
*/
package cn.sxt.decorator; public interface ICar {
void move(); } //具体构件对象,被装饰对象,真实对象:普通的汽车
class Car implements ICar{
public void move() {
System.out.println("一辆普通的车");
}
} //装饰组件(们的祖宗),要传进去一个被装饰对象
class SuperCar implements ICar{
protected ICar car; public SuperCar(ICar car) {
this.car=car;
}
@Override
public void move() {
car.move();//调用的是接口中的move方法,因为car是ICar类的对象
}
} //各种具体装饰
class FlyCar extends SuperCar{ public FlyCar(ICar car) {
super(car);
}
public void fly() {
System.out.println("天上飞");
} @Override
public void move() {
super.move();//表示调用父类SuperCar的move方法
fly();
}
} class WaterCar extends SuperCar{ public WaterCar(ICar car) {
super(car);
}
public void swim() {
System.out.println("水中潜");
} @Override
public void move() {
super.move();//表示调用父类SuperCar的move方法
swim();
}
} class AICar extends SuperCar{ public AICar(ICar car) {
super(car);
}
public void auto() {
System.out.println("自动驾驶");
} @Override
public void move() {
super.move();//表示调用父类SuperCar的move方法
auto();
}
}

【客户端】

/**
*
*/
package cn.sxt.decorator; public class Client {
public static void main(String[] args) {
Car car=new Car();//被装饰对象,真实角色
car.move();
System.out.println("----增加新的功能:天上飞----");
FlyCar flyCar=new FlyCar(car);
flyCar.move();
System.out.println("----增加新的功能:天上飞+水下潜----");
WaterCar waterCar=new WaterCar(flyCar);//直接传入一个飞行汽车,在飞行汽车的基础上搞装饰(加水里游)
waterCar.move();
System.out.println("----增加新的功能:天上飞+人工智能----");
AICar iCar=new AICar(new FlyCar(car));//也可以这样写
iCar.move(); }
}

【UML类图】

示例场景:

– IO中输入流和输出流的设计

– Swing包中图形界面构件功能

– Servlet API 中提供了一个request对象的Decorator设计模式的默认实现类HttpServletRequestWrapper,HttpServletRequestWrapper类,增强了request对象的功能。

– Struts2中,request,response,session对象的处理

• 总结:

装饰模式(Decorator)也叫包装器模式(Wrapper)装饰模式降低系统的耦合度,可以动态的增加或删除对象的职责,并使得需要装饰的具体构建类和具体装饰类

可以独立变化,以便增加新的具体构建类和具体装饰类。

• 优点:
– 扩展对象功能,比继承灵活,不会导致类个数急剧增加;

– 可以对一个对象进行多次装饰,创造出不同行为的组合,得到功能更加强大的对象

– 具体构建类和具体装饰类可以独立变化,用户可以根据需要自己增加新的具体构件子类和具体装饰子类。
• 缺点:
– 产生很多小对象。大量小对象占据内存,一定程度上影响性能。

– 装饰模式易于出错,调试排查比较麻烦。

与桥接模式的区别:

两个模式都是为了解决过多子类对象问题。但他们的诱因不一样。桥模式是对象自身现有机制沿着多个维度变化,是既有部分不稳定。

装饰模式是为了增加新的功能。

二、外观模式(facade:正面,外表)

【各个政府机构接口】

/***
* 工商局
*/
package cn.sxt.facade; public interface AIC {
void checkName();
} class HaidianAIC implements AIC{
public void checkName() {
System.out.println("在海淀区工商局检查公司名字是否重名!"); }
} /**
*银行
*/
package cn.sxt.facade; public interface Bank {
void openAccount(); } class ICBC implements Bank{
@Override
public void openAccount() {
System.out.println("在中国工商银行开设公司账户!"); }
} /***
* 国家质检局
*/
package cn.sxt.facade; public interface SAMR {
void orgCode();
} class HaidianSAMR implements SAMR{
@Override
public void orgCode() {
System.out.println("在海淀区质检局办理组织机构登记代码证!"); }
} /***
* 税务局
*/
package cn.sxt.facade; public interface Tax {
void taxCertificate(); } class HaidianTax implements Tax{ public void taxCertificate() {
System.out.println("在海淀区税务局办理税务登记!"); }
}

【政府服务大厅】

/***
*注册公司流程
*政府综合办事服务大厅,客户只需要与它打交道即可
*服务中心去调用各个机构的方法,去与各个机构打交道
*/
package cn.sxt.facade; public class Register {
public void registerCompany(){
AIC aic=new HaidianAIC();
Bank icbc=new ICBC();
SAMR samr=new HaidianSAMR();
Tax tax=new HaidianTax();
aic.checkName();
icbc.openAccount();
samr.orgCode();
tax.taxCertificate();
}
}

【客户端】

/***
* 客户
*/
package cn.sxt.facade; public class Client {
public static void main(String[] args) {
//未采用外观模式的情况,需要一个机构一个机构去跑
/* AIC aic=new HaidianAIC();
Bank icbc=new ICBC();
SAMR samr=new HaidianSAMR();
Tax tax=new HaidianTax();
aic.checkName();
icbc.openAccount();
samr.orgCode();
tax.taxCertificate();*/ //采用外观模式,直接与政府服务中心打交道即可,效果一样
new Register().registerCompany();// Register re=new Register(); re.registerCompany(); }
}

开发中常见的场景:
频率很高,哪里都会遇到。各种技术和框架中,都有外观模式的使用。如:JDBC封装后的,commons提供的DBUtils类,Hibernate提供的工具类、Spring JDBC工具类等。

                     

[19/04/27-星期六] GOF23_结构型模式(装饰模式、外观模式)的更多相关文章

  1. [19/04/28-星期日] GOF23_结构型模式(享元模式)

    一.享元模式(FlyWeight,轻量级) [共享类与非共享类] /*** *FlyweightFactory享元工厂类: 创建并管理享元对象,享元池一般设计成键值对 */ package cn.sx ...

  2. 结构型设计模式之外观模式(Facade)

    结构 意图 为子系统中的一组接口提供一个一致的界面,F a c a d e 模式定义了一个高层接口,这个接口使得这一子系统更加容易使用. 适用性 当你要为一个复杂子系统提供一个简单接口时.子系统往往因 ...

  3. Java门面模式(或外观模式)

    门面模式(或外观模式)隐藏系统的复杂性,并为客户端提供一个客户端可以访问系统的接口. 这种类型的设计模式属于结构模式,因为此模式为现有系统添加了一个接口以隐藏其复杂性.门面模式涉及一个类,它提供客户端 ...

  4. 一天学习两个设计模式之Facade模式(外观模式,结构型模式)

    程序这东西随着时间推移,程序会越来越大,程序中的类越来越多,而且他们之间相互关联,这会导致程序结构变得越来越复杂.因此我们在使用他们时候,必须要弄清楚他们之间的关系才能使用他们. 特别是在调用大型程序 ...

  5. GoF23种设计模式之结构型模式之外观模式

    一.概述         为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用. 二.适用性 1.当你要为一个复杂子系统提供一个简单接口的时候.子系统 ...

  6. 结构型模式(五) 外观模式(Facade)

    一.动机(Motivate) 在软件系统开发的过程中,当组件的客户(即外部接口,或客户程序)和组件中各种复杂的子系统有了过多的耦合,随着外部客户程序和各子系统的演化,这种过多的耦合面临很多变化的挑战. ...

  7. 七个结构模式之外观模式(Facade Pattern)

    定义: 为子系统的一组接口提供一个统一的入口,从而降低系统之间的耦合度,提高子系统的可用性.外观模式又称为门面模式,是迪米特法则的一个体现,主要目的就是降低耦合. 结构图 Facade:抽象外观类,子 ...

  8. 【设计模式最终总结】桥接模式 VS 外观模式

    差异点 外观模式,是把功能通过一个接口提供出来,方便日后更换实现,或者这种实现可以由多方提供,但同时只用一个.典型例子:@Slf4j 桥接模式,多个维度,每个维度提供一个接口,这些接口集中在一个类中, ...

  9. [19/04/26-星期五] GOF23_结构型模式(桥接模式、组合模式)

    一.桥接模式(bridge) 场景:商城系统中常见的商品分类,以电脑为例,首先想到使用多层继承结构. —— 台式机(联想台式机.戴尔台式机.神舟台式机) 电脑    ——笔记本(联想笔记本.戴尔笔记本 ...

随机推荐

  1. 使用Docker镜像部署ELK日志系统

    使用Docker部署elasticsearch.logstash.kibana 指定版本:6.7.1 (建议使用同一的版本.屏蔽三个软件间的不兼容性) 下载镜像: docker pull elasti ...

  2. nodejs应用离线安装部署、卸载

    公司写的文档,直接粘贴过来了: 本文档提供node应用一键安装.部署.卸载说明,包含对应脚本文件 默认版本:1.nodejs:v6.11.2.linux-x642.全局npm包:pm2.supervi ...

  3. 怎么使用fiddler 测试post get 接口

    直接上图 测试 post

  4. layui——上传图片,并实现放大预览

    一般上传文件后会返回文件的路径,然后存储到数据库,那么首先实现上传后的放大和删除功能 function uploadSmallPic() { var upload = layui.upload; up ...

  5. spring 与 springmvc 的区别和定义

    前言:(内附 spring 下载地址,可以选择需要的版本,给有需要的朋友)补充一下基础知识,spring 的定义和 springmvc 的定义,来源于百度百科. spring 源码下载地址 https ...

  6. Java 并发:Executor

    异常捕获 以前使用executor的时候,为了记录任务线程的异常退出会使用ThreadFactory来设置线程的UncaughtExceptionHandler,但是按照书上的验证发现,采用execu ...

  7. stm32f10x单片机进阶--spi使用

      使用SPI与外部flash(MX25L6406EM21)IC通信 连接方式                    如上图所示,MCU通过SPI2与外部flash芯片进行相连接. MCU spi2初 ...

  8. JS 计算时间差,(引入外部字体文件)

    JavaScript Date() 对象: new Date() :时间对象,会把当前时间作为其初始值: setFullYear() :用于设置月份,可有三个参数,setFullYear(year,m ...

  9. Raspberry Pi - Huawei HiLink E3256 3G modem to ethernet adapter

    Raspberry Pi - Huawei HiLink E3256 3G modem to ethernet adapter This page documents how to configure ...

  10. jquery-animate()动画

    一.animate()语法 $(“选择器”).animate({CSS样式},时间,运动方式,回调函数); 参数说明: 参数1:CSS属性名,属性值,JSON格式{"属性名":&q ...