[19/04/27-星期六] GOF23_结构型模式(装饰模式、外观模式)
一、装饰模式(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工具类等。
最新文章
- Dojo动画原理解析
- 安装RabbitMQ遇到的问题
- 正确运用synchronized和二次判断 实现多线程安全
- SQL2008-功能设置
- Oracle EBS-SQL (BOM-1):检查供应类型错误.sql
- Vim编辑器的使用和基本配置
- Shorten Diameter
- js观察者模式与Model
- mysql关闭/启用外键约束
- Python爬虫番外篇之Cookie和Session
- JBOD
- Redis 概念以及底层数据结构
- raise error
- 查看python中模块的所有方法
- spring整合mybatisXML版
- 简单说throw和throws的区别
- URI Scheme注册伪协议实现远程命令执行
- zookeeper 详解
- js与native的交互
- PAT 1069 微博转发抽奖
热门文章
- jQuery事件篇---过滤选择器 &; 表单选择器
- [javaSE] GUI(事件监听机制)
- 十、获取异步线程返回值Callable
- java.lang.SecurityException: Permission Denial: reading com.android.providers.media.MediaProvider uri content://media/external/images/media/20 from pid=711, uid=10074 requires android.permission.READ_
- 3.java设计模式-建造者模式
- Apache shiro的简单介绍与使用(与spring整合使用,并加入ehcache缓存权限数据)
- Python Django 路由分发
- 用Jq遍历一个div里面的所有input 并判断是否为空?
- Java中的继承:父类和子类的关系
- Storage 的使用