一、装饰模式(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工具类等。