增强对象的方法一共三种,分别是:
继承
装饰者模式
动态代理
现在分别说一下三个增强方式的特点:
继承:
1.增强的内容是死的,不能动
2.被增强的类也是死的。
装饰者模式:
1.增强的内容是不能修改的
2.被增强的对象可以是任意的
动态代理:
1.增强的内容是可以修改的---执行的逻辑
2.被增强的类对象也可以切换
从上面可以看出动态代理技术的对象的增强方式最灵活,因为它可以灵活的组装逻辑和被增强的对象。而继承是灵活 性,最差的,装饰者模式在中间,在这篇文章中,我只说装饰者模式
装饰者模式定义:指的是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。
为什么要用装饰者模式:当我们在一些场景下需要增强实现某一个接口或者某一个类的任意一个子类的对象的时候,可以用装饰者模式。这样的话,就不必知道增强的具体对象是什么,而且增强的范围比较广。举个栗子
有一个接口:
public interface A {
public void add();
public void xxx();
}
它的其中一个实现类:
public class B implements A{
@Override
public void add() {
// TODO Auto-generated method stub
System.out.println("我是B");
}
@Override
public void xxx() {
// TODO Auto-generated method stub
System.out.println("我是B的XXX");
}
}
如果我们想对A接口的一个实现类对象的add方法增强,那么可不可以用继承呢?答案是可以的,但是如果A的实现类有十几个,那么难道你还要继承十几个类吗?如果A的实现类更多呢?那么需要继承的类就会几何倍数增涨。所以这种情况下,就要考虑装饰者模式了。下面上代码,再来解释。
public class C implements A{
private A implA;
public C() {
// TODO Auto-generated constructor stub
}
public C(A implA) {
this.implA = implA;
}
@Override
public void add() {//增强点
System.out.println("我是C");
implA.add();
// TODO Auto-generated method stub
}
@Override
public void xxx() {
// TODO Auto-generated method stub
System.out.println("我是C的XXX");
}
}
C的类中有一个A接口的私有属性,然后提供一个无参构造器和一个有参构造器。有参构造器,提供的参数就是A接口实现类的对象,在内部为implA赋值,然后为实现类的add方法增强,即在implA.add()方法前面多输入一句话。这个被增强的方法就是增强点。为什么其他方法不增强呢?因为其他方法都增强了,那么这个装饰者模式意义何在,还不如重新写一遍,一般只增强其中一个方法。这就是装饰者模式的一般用法。下面来一个main方法。
public static void main(String[] args) {
C c= new C(new B());
c.add();
}
结果
我是C
我是B
这就完成了对A的实现类B的对象的add方法的增强,这个位置也可以换成A的实现类D的对象........。都可以,是不是对装饰者模式一目了然了呢?
应用场景:java的jdk中就有提供装饰者模式,最常用的装饰者模式就是流,
四个原始流:
1.字节流:InputStream OutputStream
2.字符流:Reader,Writer
拿出其中一个栗子,
FileInputStream,是一个InputStream的实现类
BufferedInputStream:是一个InputStream的实现类
BufferedInputStream有一个构造器就是new BufferedInputStream(InputStream is);
可以这样做BufferedInputStream bis = new BufferedInputStream(FileInputStream fis);
完成对对象的增强。BufferedInputStream将节点流FileInputStream包装成了装饰流,提高了FileInputStream对象的读速度
其实本质还是FileInputStream的对象在起作用。
作用:我们经常利用这种方式来给自己的文件加密。