装饰者模式
【应用场景】
装饰者模式又称为包装模式,主要是为客户端透明的扩展被调用者的功能。动态的给一个对象附加上更多的功能,是继承关系的一个替代方案。我们可以不断进行装饰,丰富扩展功能,形成一条装饰者链。其实我们子类重写父类的方法也是同样的思想,只是相比较下装饰者模式更加的灵活,能动态的增加或删除功能(就是编写起来会麻烦些)。
结构类图
1. 定义一个接口,规范某个行为。
2. 被装饰者实现这个接口,实现最基本的功能。
3. 编写装饰者角色,实现同一个接口(这个类的存在是为了避免我们对原有对象的操作)。
4. 根据业务需求,编写一个或多个具体的装饰者提供相应的功能。
案例编写
一:先定义接口,规范行为
/** * 一:抽象接口,规范行为 * @author wuLei */ public interface User { public void skill(); }
二: 编写被装饰的类,实现基本功能。
/** * 二:具体的的行为类(被装饰者) * @author wuLei */ public class Wulei implements User{ @Override public void skill() { System.out.println("大家好,我是吴磊!"); } }
三:定义装饰者角色
/** * 三:定义装饰者角色,同样要继承于接口 * @author wuLei */ public abstract class DecoratorUser implements User{ private User user; //通过有参构造获取user的实例 public DecoratorUser(User user) { this.user = user; } @Override public void skill() { // 重写之前的方法,让它具备之前的功能。 user.skill(); } }
四:定义具体的装饰者添加新功能,我这里编写了3各类扩展功能。
/** * 四:具体的装饰者1 * @author wuLei */ public class Wulei1 extends DecoratorUser{ public Wulei1(User user) { super(user); } @Override public void skill() { // 重写之前的方法,让它具备之前的功能。 super.skill(); //新增一个功能 springCloud(); } private void springCloud() { System.out.println("我会SpringCloud技术栈"); } }
/** * 五:具体的装饰者2 * @author wuLei */ public class Wulei2 extends DecoratorUser{ public Wulei2(User user) { super(user); } @Override public void skill() { // 重写之前的方法,让它具备之前的功能。 super.skill(); //新增一个功能 linux(); } private void linux() { System.out.println("我会Linux环境部署"); } }
/** * 六:具体的装饰者3 * @author wuLei */ public class Wulei3 extends DecoratorUser{ public Wulei3(User user) { super(user); } @Override public void skill() { // 重写之前的方法,让它具备之前的功能。 super.skill(); //新增一个功能 hadoop(); } private void hadoop() { System.out.println("我会hadoop大数据"); } }
五:编写测试类
/** * 七: 测试 * @author wuLei */ public class Test { public static void main(String[] args) { Wulei3 w3 = new Wulei3(new Wulei2(new Wulei1(new Wulei()))); w3.skill(); System.out.println("--------------"); Wulei2 w2 = new Wulei2(new Wulei()); w2.skill(); } } ==================== 【控制台输出结果】 大家好,我是吴磊! 我会SpringCloud技术栈 我会Linux环境部署 我会hadoop大数据 -------------- 大家好,我是吴磊! 我会Linux环境部署
JDK实例:
从下图I/O库的结构图可以看出:
抽象构件角色:由InputStream扮演。这是一个抽象类,为各种子类型提供统一的接口。
具体构件由ByteArrayInputStream、FileInputStream、PipedInputStream、StringBufferInputStream等类扮演。它们实现了抽象构件角色所规定的接口。
抽象装饰角色:由FilterInputStream扮演。它实现了InputStream所规定的接口。
具体装饰几个类扮演,分别是BufferedInputStream、DataInputStream以及两个不常用到的类LineNumberInputStream、PushbackInputStream。
所以,我们在调用的时候,可以做如下组合,形成装饰者链:
InputStream in = new LineNumberInputStream(new BufferedInputStream(newFileInputStream(file)));