一、装饰模式(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. java中的奇葩 “:”

    一.经常使用java的人有没有发现java也可以将汉字作为标识符出现呢? 在Java语言中,标识符是以字母.下划线(_)或美元符($)开头,由字母.数字.下划线(_)或美元符($)组成的字符串 真的输 ...

  2. High Performance MySQL笔记:count

    在SQL中使用count()好像是非常自然的事情: SELECT COUNT(*) FROM TABLE_NAME; 有时候确实会想过,count(*)和单独的count(column_name)有什 ...

  3. 洛谷P3939 数颜色(二分 vector)

    题意 题目链接 Sol 直接拿vector维护每种颜色的出现位置,然后二分一下. #include<bits/stdc++.h> using namespace std; const in ...

  4. 使用SVG绘制流程图

    本篇主要记录流程图的实现过程中的难点和核心技术点,先上效果图: 节点可以任意拖拽,曲线跟随变化 正在连接的线 1.节点实现 流程图是基于SVG绘制的,节点主要利用 g 和 foreignObject的 ...

  5. Slf4j打印异常的堆栈信息

    一.前言 直接用logger.info("异常信息为:"+e)或者logger.info(e.getMessage())只能记录到异常的描述信息,却没有其异常具体发生在哪一行代码. ...

  6. Android 显示html标签或者带图片

    Android中显示html文件要用Html.fromHtml(...)处理过的返回值,返回值可以成为setText()的参数. 只显示带文本的html可以用下面的方法处理html文件. public ...

  7. Qt获取控件位置,坐标总结

    总结的结果是: QMouseEvent中两类坐标系统,一类是窗口坐标,一类是显示器坐标.   总结一:经过试验,QMouseEvent::globalPos()  和 QCursor::pos()效果 ...

  8. GPG error: http://extras.ubuntu.com trusty Release: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY F60F4B3D7FA2AF80

    今天在更新运行apt-get update的时候出现了如下的错误: W: GPG error: http://extras.ubuntu.com trusty Release: The followi ...

  9. windows 下 openssl 生成RSA私钥公钥以及PKCS8

    生成RSA私钥 打开bin文件夹下面的openssl.exe,输入genrsa -out rsa_private_key.pem 1024 把RSA私钥转换成PKCS8格式 输入命令pkcs8 -to ...

  10. spring cloud Eureka server配置

    参考:http://www.ityouknow.com/springcloud/2017/05/10/springcloud-eureka.html spring boot版本:2.0.3.RELEA ...