装饰器
介绍:
- 要修改一个类的方法,该类已经存在时,用到装饰器模式
- 装饰者要和被装饰者实现同一个接口
- 装饰者要声明一个以被装饰者接口为入参的构造器
- 装饰者内部,想要改造的方法自己实现,不想要改造的方法使用被装饰者的方法
- 使用时,已有一个被装饰者的对象,new一个装饰者,把被装饰者传进去
- 之后该接口的实现类就可以使用该装饰类
缺点:如果该类有多个方法时,写一个装饰类会有很多代码冗余,代码不太雅观
例子如下:存在一个接口Master和一个实现类Sub,想要改造该类的chi方法,去写一个装饰类SubZs,实现Master,声明一个构造器,入参为Master。
//接口
interface Master{
public void chi();
public void pao();
}
//被装饰者
class Sub implements Master{
@Override
public void chi() {
System.out.println("chifan");
}
@Override
public void pao() {
System.out.println("paobu");
}
}
//装饰者
class SubZs implements Master{
private Master m;
public SubZs(Master m){
this.m=m;
}
@Override
public void chi() {
System.out.println("hehe~");
m.chi();
}
@Override
public void pao() {
m.pao();
}
}
测试一把:
public class ZhuangShi {
public static void main(String[] args) {
Master m = new Sub();
Master m2 = new SubZs(m);
m2.chi();
}
}
结果(chi的方法被装饰了):
hehe~
chifan
静态代理
静态代理和装饰器的代码看似一样,但是静态代理生来就不是和装饰器比较的
他们所适应的场景不同,装饰器是把存在的类对象装饰一下,而代理模式是把类找一个代理者
静态代理是与动态代理区别的
动态代理
动态代理分为jdk和cglib,下面分别说明
- jdk动态代理
最开始java提供了jdk的动态代理,被代理的类必须实现一个接口,代码如下:
/**
声明一个接口
*/
interface Master{
public void chi();
}
/**
被代理者,Sub实现接口
*/
class Sub implements Master{
@Override
public void chi() {
System.out.println("chifan");
}
}
/**
代理者
*/
class proxy{
Master a;
public proxy(){};
public Object getInstance(Master b){
this.a = b;
return Proxy.newProxyInstance(a.getClass().getClassLoader(), a.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object arg0, Method arg1, Object[] arg2)
throws Throwable {
if(arg1.getName().equals("chi")){
System.out.println("hehe");
return null;
}else{
return arg1.invoke(a, arg2);
}
}
});
}
}
测试一把:
public class TestJdkProxy{
public static void main(String[] args) {
Master a = (Master)new proxy().getInstance(new Sub());
a.chi();
}
}
结果是:
hehe
- cglib动态代理
被代理的类不需要实现接口,内部使用了继承,具体见代码如下:
/**
* 被代理者
*/
class Sub{
public void chi(){
System.out.println("chifan");
}
}
/**
代理者
*/
class CglibProxy{
private Sub s;
public Object getInstance(Sub ss){
this.s=ss;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(ss.getClass());
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object proxy, Method method, Object[] arg2,
MethodProxy methodProxy) throws Throwable {
if("chi".equals(method.getName())){
System.out.println("hehe");
return null;
}else{
return method.invoke(s, arg2);
}
}
});
return enhancer.create();
}
}
测试一把:
public class TestCglibProxy {
public static void main(String[] args) {
Sub subProxy = (Sub)new CglibProxy().getInstance(new Sub());
subProxy.chi();
}
}
结果:
hehe