1.前言

为什么要将代理模式与适配器模式放在一起来说呢?因为它们有许多的共同点,当然也有一些不同的地方。首先两者都是属于结构型模式。结构型模型是这样定义的:

结构型模式涉及到如何组合类和类以获得更大的结构,结构型类模式采用继承机制来组合接口或实现

1)代理模式与适配器模式都分别有继承、接口方式实现的子分类模式。基于接口实现的代理模式称为静态代理模式、JDK(动态)代理模式,基于继承实现的代理模式称为Cglib(动态)代理模式。基于接口(同时含类继承)实现的适配器模式称为类适配器模式,(只)基于继承(使用委托)实现的适配器模式称为类适配器模式。

2)代理模式是为其他类提供一种代理以控制对这个类的访问。我们不直接去接触目标类,而是直接操作代理类,代理类再去操作目标类。因为不直接接触目标类,因此我们可以在代理类的同名方法中添加或删除功能模块,而不用去修改目标类的原方法。

而适配器模式则主要是协调现实与需求的差异,减少对已有代码的改动,适配不同的接口、类类型。项目实施中可能会出现这样的情况:当前已完成的项目的某一个包内的各个类实现了一些特定的接口,而客户提出了新的需求,要求实现他所指定的那些接口(抛弃原有的方法或接口),但其业务细节却是相同、完全一样的。此时,我们可能并不想复制粘贴原代码到新的方法中去,这就需要将一个类的接口转换成新需求的另一个接口。

2.代理模式

1)静态代理

静态代理,必须提供一(多)个公用的接口。目标类和代理类都要实现这个接口,外界调用代理类的(接口)方法,代理类的方法再去调用目标类(接口)的方法。

public class StaticProxy {

    /**
* 定义一个接口
*
* @author Administrator
*
*/
public static interface Human {
void behave();
} /**
* 定义一个实现Human接口的具体类Student
*
* @author Administrator
*
*/
public static class Student implements Human {
String name; public Student() {
} public Student(String name) {
super();
this.name = name;
} @Override
public void behave() {
System.out.println(name + "上学去了");
}
} /**
* 定义静态代理类
*
* @author Administrator
*
*/
//代理类和目标类都实现了Human方法
public static class StudentProxy implements Human{
private Human target; // 目标对象
/**
* 构造方法
*
* @param target 目标对象
*/
protected StudentProxy(Human target) {
this.target = target;
} @Override
public void behave() {
System.out.println("+++++++目标方法执行前打印加号+++++++");
target.behave();
System.out.println("*******目标方法执行后打印星号*******");
}
}
public static void main(String[] args) {
Human studentProxy=new StudentProxy(new Student("何峰"));
studentProxy.behave();
}
}

静态代理的各个静态内部类

定义一个公用的接口

    public static interface Human {
void behave();
}

实现接口的目标类

    public static class Student implements Human {
String name;
public Student() {
}
public Student(String name) {
super();
this.name = name;
}
@Override
public void behave() {
System.out.println(name + "上学去了");
}
}

实现接口的代理类

    public static  class StudentProxy implements Human{
private Human target; // 目标类
protected StudentProxy(Human target) {
this.target = target;
} @Override
public void behave() {
System.out.println("+++++++目标方法执行前打印加号+++++++");
target.behave();
System.out.println("*******目标方法执行后打印星号*******");
}
}

主方法测试

public static void main(String[] args) {
Human studentProxy=new StudentProxy(new Student("何峰"));
studentProxy.behave();
}

控制台结果输出

2)JDK动态代理

JDK动态代理,主要是利用JDK提供的API动态生成代理类实例。

我们不需要去写一个具体代理类,只需要一个代理工厂即可,JDK的系统API将在运行时动态生成代理类的字节码,并此字节码将加载到JVM中,在JVM中直接构建代理类(不需要将class文件读取到内存中)。

要用到的JDK的API

(1)java.lang.reflect.Proxy工具类

我们主要会用到的静态方法   static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h )

这个静态方法将能够动态构建一个实现了和目标类相同的接口的代理类(具体实现的接口个数,此方法中的参数interfaces有关),此方法的三个参数分别是目标类的类加载器loader、目标类实现的接口数组interfaces、 InvocationHandler类handler。

(2)java.lang.reflect.InvocationHandler接口

此接口只有一个抽象方法  public Object invoke(Object proxy, Method method, Object[] args)throws Throwable

这个抽象方法的三个参数分别表示代理类proxy, 目标类方法method,目标类方法的参数args。

这是一个回调方法,当我们调用代理类所实现的接口方法(和目标类相同的接口相同)时,java虚拟机会调用此方法。所以重写此方法非常重要,可以在此方法中添加我们所需要的增强效果。

实现细节

为了直观简便地测试效果,特别将所需类都作为内部类放在JDKProxy中

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy; public class JDKProxy { /**
* 定义一个接口
*
* @author Administrator
*
*/
public static interface Human {
void behave();
} /**
* 定义一个实现Human接口的具体类Student
*
* @author Administrator
*
*/
public static class Student implements Human {
String name; public Student() {
} public Student(String name) {
super();
this.name = name;
} @Override
public void behave() {
System.out.println(name + "上学去了");
}
} /**
* 定义动态代理抽象工厂类
*
* @author Administrator
*
*/
// 继承InvocationHandler,但不实现其接口方法,接口方法的具体实现交给抽象工厂类的子类去完成
public static abstract class ProxyFactory implements InvocationHandler {
// 访问权限设置为保护级,其子类能继承到此成员变量
protected Object target; // 目标对象 /**
* 构造方法
*
* @param target 目标对象
*/
// 只有这一个单参数构造方法,访问权限同时也设为保护级,则子类必须显式调用此构造方法
protected ProxyFactory(Object target) {
super();
this.target = target;
} /**
* 动态生成代理对象
*
* @return 代理对象
*/
// 方法设为final,防止子类重写此方法
public final Object getProxyInstance() {
/*
* Proxy.newProxyInstance方法的三个参数依次是目标对象的类加载器loader、目标对象实现的接口数组interfaces、
* InvocationHandler对象handler。
* InvocationHandler是个接口,而当前抽象类implements此接口,此处的抽象类并没有具体实现此接口,具体实现将交给子类
*
*/
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
} } /**
* 上小学的代理工厂类
* @author Administrator
*
*/
public static class PrimaryProxyFactory extends ProxyFactory { /**
* 动态生成代理对象
*
* @return 代理对象
*/
private PrimaryProxyFactory(Object target) {
super(target);
} /**
* 实现InvocationHandler接口,增强目标对象实现接口的方法
*/
@Override
public final Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("小学学校离家5km。"); //目标对象方法执行前的修饰
Object returnVal = method.invoke(this.target, args); //调用目标对象的相应方法
System.out.println("早上去上学费时30分钟。");//目标对象方法执行后的修饰
return returnVal;
}
} /**
* 上高中的代理工厂类
* @author Administrator
*
*/
public static class SeniorProxyFactory extends ProxyFactory {
/**
* 动态生成代理对象
*
* @return 代理对象
*/
protected SeniorProxyFactory(Object target) {
super(target);
} @Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("高中学校离家50km。");
Object returnVal = method.invoke(this.target, args);
System.out.println("去一次学校就要费时两个小时。");
return returnVal;
} } public static void main(String[] args) {
Student stu = new Student("李高峰");
//创建代理工厂对象
ProxyFactory primaryProxyFactory = new PrimaryProxyFactory(stu);
//代理对象向上转型为Human接口
Human proxyPrimaryHuman = (Human) primaryProxyFactory.getProxyInstance();
//代理对象执行接口方法
proxyPrimaryHuman.behave(); System.out.println(""); ProxyFactory seniorProxyFactory = new SeniorProxyFactory(stu);
Human proxySeniorHuman = (Human) seniorProxyFactory.getProxyInstance();
proxySeniorHuman.behave(); } }

JDK代理的各个内部类

先定义一个接口Human

    public static interface Human {
void behave();
}
定义一个实现Human接口的目标类Student
    public static class Student implements Human {
String name;
public Student() {
}
public Student(String name) {
super();
this.name = name;
}
@Override
public void behave() {
System.out.println(name + "上学去了");
}
}

定义动态代理的抽象工厂类

	// 继承InvocationHandler,但不实现其接口方法,接口方法的具体实现交给抽象工厂类的子类去完成
public static abstract class ProxyFactory implements InvocationHandler {
// 访问权限设置为保护级,其子类能继承到此成员变量
protected Object target; // 目标对象 /**
* 构造方法
*
* @param target 目标对象
*/
// 只有这一个单参数构造方法,访问权限同时也设为保护级,则子类必须显式调用此构造方法
protected ProxyFactory(Object target) {
super();
this.target = target;
} /**
* 动态生成代理对象
*
* @return 代理对象
*/
// 方法设为final,防止子类重写此方法
public final Object getProxyInstance() {
/*
* Proxy.newProxyInstance方法的三个参数依次是目标对象的类加载器loader、
* 目标对象实现的接口数组interfaces、InvocationHandler对象handler。
* InvocationHandler是个接口,而当前抽象类implements此接口,此处的抽象类并没有具体实现此接口,具体实现将交给子类
*/
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
} }

定义抽象工厂类的子类(实现类)

    /**
* 上小学的代理工厂类
* @author Administrator
*/
public static class PrimaryProxyFactory extends ProxyFactory {
public PrimaryProxyFactory(Object target) {
super(target);
} /**
* 实现InvocationHandler接口,增强目标类实现接口的方法
*/
@Override
public final Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("小学学校离家5km。"); //目标类方法执行前的修饰
Object returnVal = method.invoke(this.target, args); //调用目标类的相应方法
System.out.println("早上去上学费时30分钟。");//目标类方法执行后的修饰
return returnVal;
}
} /**
* 上高中的代理工厂类
* @author Administrator
*
*/
public static class SeniorProxyFactory extends ProxyFactory { public SeniorProxyFactory(Object target) {
super(target);
} @Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("高中学校离家50km。");
Object returnVal = method.invoke(this.target, args);
System.out.println("去一次学校就要费时两个小时。");
return returnVal;
}
}

主方法内进行效果测试

    public static void main(String[] args) {
Student stu = new Student("李高峰");
//创建代理工厂类
ProxyFactory primaryProxyFactory = new PrimaryProxyFactory(stu);
//代理类向上转型为Human接口
Human proxyPrimaryHuman = (Human) primaryProxyFactory.getProxyInstance();
//代理类执行接口方法
proxyPrimaryHuman.behave(); System.out.println("");
ProxyFactory seniorProxyFactory = new SeniorProxyFactory(stu);
Human proxySeniorHuman = (Human) seniorProxyFactory.getProxyInstance();
proxySeniorHuman.behave();
}

控制台效果输出

3)Cglib代理

静态代理和JDK动态代理都必须要求目标类实现了一(多)个接口,而对未实现任何接口的目标类无法进代理处理。Cglig动态代理就是为了解决这一问题而产生的代理技术。它是在运行时,利用asm字节码框架,动态生成目标类的子类的字节码,并加载到java虚拟机中,运行期动态地创建目标类的子类类。Cglib代理需要外部框架支持,而spring-core-xxx.jar包中就含有Cglib所需的class文件。

使用Cglib代理有以下两点要求:

(1)目标类不能被定义为final。---------------------------   定义的final的类不能被继承扩展,当然就不可能创建出它的(代理类)子类

(2)目标类的方法不能为final或static修饰-------------    final方法不能被重写,(子类)代理类也就不能对此方法进行扩展。静态方法与类本身相关联,不依赖于实例类存在,无法实现多态。

Cglib代理的关键点:

(1)方法拦截器接口  org.springframework.cglib.proxy.MethodInterceptor

此接口中只有一个方法 public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable

此方法为回调方法,在运行期间此方法是将动态地生成代理类(子类)的代理方法(重写目标类的方法)。

此方法的四个参数分别是代理类类proxy、目标类方法类method、目标类方法的参数args、代理类的方法(spring框架中的数据类型,不同于JDK中的Method)类methodProxy。

(2)代理方法增强工具类  org.springframework.cglib.proxy.Enhancer

其方法一 void  setSuperclass(Class  supperClass) 设置目标类(即代理类的父类)的Class模板类
其方法二 void  setCallback(MethodInterceptor methodInterceptor) 设置回调方法,其intercept(......)方法定义了代理类(即目标类的子类)的方法重写规范
其方法三   Object  create() 创建并返回代理类类 

实现过程

import java.lang.reflect.Method;

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy; import proxy3.ProxyFactory; public class CglibProxy { public static class Student {
private String name = "xxx"; public void setName(String name) {
this.name = name;
} public Student() {
} public void behave() {
System.out.println(name + "上学去了");
}
} /**
* 定义动态代理工厂类
*/
// 继承MethodInterceptor
public static class ProxyFactory implements MethodInterceptor {
private static final ProxyFactory proxyFactory;
static {
proxyFactory = new ProxyFactory();
} /**
* 返回代理工厂单例
* @return
*/
public static ProxyFactory getThis() {
return proxyFactory;
} /*
* 构造方法私有化
*/
private ProxyFactory() {
} /**
* 创建目标类的代理对象
*
* @param targetClass 目标类的元类
* @return 代理对象
*/
@SuppressWarnings("unchecked")
public <T> T createProxyInstance(Class<T> targetClass) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(targetClass);
enhancer.setCallback(this);
return (T) enhancer.create(); //代理对象向上转型为父类类型,即目标类类型
//return (T) Enhancer.create(targetClass, this); 此方法可一步到位
} /*
*拦截器接口MethodInterceptor中的方法
*/
@Override
public Object intercept(Object proxyObj, Method method, Object[] args, MethodProxy methodProxy)
throws Throwable {
Object returnVal = null;
if (method.getName().startsWith("be")) { //只对特定方法拦截
System.out.println("上学前记得带作业");
returnVal = methodProxy.invokeSuper(proxyObj, args); //调用目标方法
System.out.println("小心路上的汽车");
}else {
returnVal = methodProxy.invokeSuper(proxyObj, args);
} return returnVal;
}
} public static void main(String[] args) {
ProxyFactory proxyFactory=ProxyFactory.getThis();
Student stuProxy= proxyFactory.createProxyInstance(Student.class);
stuProxy.setName("小王");
stuProxy.behave();
}
}

各内部类

未实现任何接口的目标类

	public static class Student {
private String name = "xxx"; public void setName(String name) {
this.name = name;
} public Student() {
} public void behave() {
System.out.println(name + "上学去了");
}
}

  

实现MethodInterceptor接口的代理工厂类

	public static class ProxyFactory implements MethodInterceptor {
private static final ProxyFactory proxyFactory;
static {
proxyFactory = new ProxyFactory();
} /**
* 返回代理工厂单例
* @return
*/
public static ProxyFactory getThis() {
return proxyFactory;
} /*
* 构造方法私有化
*/
private ProxyFactory() {
} /**
* 创建目标类的代理对象
*
* @param targetClass 目标类的元类
* @return 代理对象
*/
@SuppressWarnings("unchecked")
public <T> T createProxyInstance(Class<T> targetClass) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(targetClass);
enhancer.setCallback(this);
return (T) enhancer.create(); //代理对象向上转型为父类类型,即目标类类型
//return (T) Enhancer.create(targetClass, this); 此方法可一步到位
} /*
*拦截器接口MethodInterceptor中的方法
*/
@Override
public Object intercept(Object proxyObj, Method method, Object[] args, MethodProxy methodProxy)
throws Throwable {
Object returnVal = null;
if (method.getName().startsWith("be")) { //只对特定方法拦截
System.out.println("上学前记得带作业");
returnVal = methodProxy.invokeSuper(proxyObj, args); //调用目标方法
System.out.println("小心路上的汽车");
}else {
returnVal = methodProxy.invokeSuper(proxyObj, args);
} return returnVal;
}
}

  

主方法内进行测试

	public static void main(String[] args) {
ProxyFactory proxyFactory=ProxyFactory.getThis();
Student stuProxy= proxyFactory.createProxyInstance(Student.class);
stuProxy.setName("小王");
stuProxy.behave(); }

  

在控制台 测试结果输出

3.适配器模式

1)类适配器模式

基本思路

类适配器模式主要应用于新需求是一个新的接口。为了适应新的需求,我们必须先实现此接口,但我们又要想复用原有的代码。此时要满足这一点,可通过继承原有的类,来复用父类的方法。综合以上的两个关键点,我们应该定义一个新的类,使其继承原有的类,同时去实现业务所需的新目标接口。

实现过程

public class ClassAdapter {

    /**
* 目标接口
* @author Administrator
*
*/
public static interface Animal {
void act();
} /*
* (现有的类)被适配者
*/
public static class Student {
private String name;
public Student() { }
public Student(String name) {
super();
this.name = name;
}
public void behave() {
System.out.println(name + "上学去了");
}
}
/**
* 适配者(器)
*
*/
public static class Actor extends Student implements Animal{ public Actor() {
super();
}
public Actor(String name) {
super(name);
} @Override
public void act() {
/**
* 调用父类Student的behave()方法,使当前act()方法产生与behave()完全相同的效果输出,
* 但在外界来看,是实现了新的行为方法,外界只会调用act方法,而不知其内部具体实现
* 实际上还是在执行behave()方法
*/
super.behave();
}
} public static void main(String[] args) {
Animal actor= new Actor("张天一");
actor.act();
}
}

类适配器模式的各个内部类

原有的学生类Student具有behave行为

    public static class Student  {
private String name;
public Student() { }
public Student(String name) {
super();
this.name = name;
}
public void behave() {
System.out.println(name + "上学去了");
}
}

新的目标需求是实现Animal接口,使其具有Animal的能力,但行为细节不用改变

    public static interface Animal {
void act();
}

定义一个新类(适配者),让其适配新的需求,同时复用已有的代码

    public static class Actor extends Student implements Animal{
public Actor() {
super();
}
public Actor(String name) {
super(name);
}
@Override
public void act() {
/**
* 调用父类Student的behave()方法,使当前act()方法产生与behave()完全相同的效果输出,
* 但在外界来看,是实现了新的行为方法,外界只会调用act方法,而不知其内部具体实现
* 实际上还是在执行behave()方法
*/
super.behave();
}
}

  

主方法测试

   public static void main(String[] args) {
Animal actor= new Actor("张天一");
actor.act();
}

控制台输出

2)对象适配器模式

设计思路

对象适配器模式主要应用于新的需求的一个(抽象)基类。在这里我们不能使用类适配器模式的所用到的继承父类、实现接口的方式去满足目标需求,因为java中不允许多根继承,只能单根继承,我们也就无法在继承(目标需求)抽象类的同时再去继承原有的类(复用原代码)。此时定义一个新类(适配者),将一个原有的类类(被适配者)作为成员变量放在这个类中,此类还要继承目标抽象类,并实现其中的抽象方法。

实现过程

public class ObjectAdapter {
/**
* 目标抽象类
* @author Administrator
*
*/
public static abstract class Animal {
public abstract void act();
} /*
* (现有的类)被适配者
*/
public static class Student {
private String name;
public Student() { }
public Student(String name) {
super();
this.name = name;
}
public void behave() {
System.out.println(name + "上学去了");
}
}
/**
* 适配者(器)
*
*/
public static class Actor extends Animal{
private Student student;
//student属性,让构造方法传的Student对象参数让其初始化
public Actor(Student student) {
super();
this.student = student;
}
@Override
public void act() {
student.behave();
}
} public static void main(String[] args) {
Animal actor=new Actor(new Student("张一峰"));
actor.act();
}
}

示例的各个内部类

现有学生类Student (被适配者)

    public static class Student  {
private String name;
public Student() { }
public Student(String name) {
super();
this.name = name;
}
public void behave() {
System.out.println(name + "上学去了");
}
}

  

目标需求的抽象类Animal

    public static abstract class Animal {
public abstract void act();
}

  

定义新类(适配者),继承(需求)抽象类,Student(被适配者)作为它的成员变量

    public static class Actor extends  Animal{
private Student student;
//student属性,让构造方法传的Student类参数让其初始化
public Actor(Student student) {
super();
this.student = student;
}
@Override
public void act() {
student.behave();
}
}

  

主方法测试

    public static void main(String[] args) {
Animal actor=new Actor(new Student("张一峰"));
actor.act();
}

  

控制台输出

4.总结

(1)代理模式,按照是代理类否由java虚拟机动态生成的,可将代理模式分为静态代理和动态代理。

代理模式,为其他类提供一种代理以控制对这个类的访问  ,主要目的就是实现对目标类的方法增强。

静态代理,需要定义接口,代理类和目标类都实现此接口,然后代理类调用接口的同名方法来调用目标类的方法。需要注意的是:此代理类需要我们手动去接口中的每个方法去写实现,并在保存编译后classpath路径中将存在这个代理类的class文件。

然而大多数情况下, 对目标类方法的增强控制代码是相同或类似的,如果接口中的方法较多或接口较多,一 一为之编写代理类的接口实现方法,会增加工作量,造成代码冗余。而动态代理,则不需要一 一编写代理类对接口的实现方法,不需要编写具体的代理类,那么classpath中就不存在代理类的class文件,但需要定义统一的接口方法实现规范,即编写一个生成代理类的代理工厂类。而在动态代理中又可分为JDK(接口)代理、Cglib代理。

JDK代理需提供接口,动态生成的代理类实现此接口,实质上是根据代理工厂类的接口实现规范(如上面的PrimaryProxyFactory的"invoke(Object proxy, Method method, Object[] args)"方法)来实现 与目标类相同方法签名的接口方法以完成方法代理;而Cglib代理不需要提供接口,动态生成的代理类会去继承目标类,实质上也是根据代理工厂类的方法重写规范(如上面的ProxyFactory类的"intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy)"方法)来重写父类的方法以实现方法代理。

(2)适配器模式,按照需求是就接口或(抽象)类,可分为类适配器模式和对象适配器模式。

适配器模式,将一个类的接口转换成客户希望的另外一个接口,它填补了“现有程序” 和“所需程序”之间的差异,增强代码的兼容复用能力,以适应不同的目标需求。

类适配器模式需要新定义一个适配器类,它实现了需求对应的接口,并继承现有的业务类,通过在接口方法中显式地调用父类的方法的方式,达到适应新需求同时又复用现有方法代码的目的。

对象适配器模式同样需要定义一个适配器类,它继承需求对应的(抽象)类,将现有的业务类作为适配器的一个成员变量,并用构造方法传入业务类实例对象的引用,以初始化此成员变量;在实现父类的抽象方法中使用委托机制(某个方法将实际处理工作交给其他对象的方法去完成),让成员变量(现有业务类对象)调用自己的方法。

(3)代理模式和适配器模式的比较

代理模式和对象适配器模式都需要持有一个对象的引用(作为成员变量),且此成员变量通过构造方法来初始化,使用委托机制完成想要的全部或部分的业务处理。

静态代理、JDK动态代理与类适配器模式都基于实现接口方法,而Cglib动态代理、对象适配器模式都基于继承(抽象)类。

从广义的角度上来看(参考C++中的多继承),实现接口方法、继承父类都属于广义上的“继承”,达成多态的效果。"继承"(包含实现接口)是设计模式中常用的策略,"继承"的目的就是代码重用和多态。无论是代理模式还是适配器模式,都是对满足新需求而应运而生的设计模式。不同之处在于,代理模式中,新的需求是具体业务有了变化,但接口或方法名没有变化;适配器模式中,新需求是接口或方法名变化了,但具体业务没有变化。为了充分利用变化中的不变因素,我们常使用广义上的“继承”机制来实现,所以代理模式和适配器模式都用到了大量的“继承”机制。

参考:Java的三种代理模式(岑宇);图解设计模式(结城浩)

漫谈设计模式(一):代理(Proxy)模式与适配器(Adapter)模式对比的更多相关文章

  1. 【原】模式之-适配器Adapter模式

    适配器Adapter模式 适配器模式(Adapter Pattern)把一个类的接口变换成客户端所期待的的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作. 模式所涉及的角色有 ...

  2. JAVA设计模式-动态代理(Proxy)示例及说明

    在Mybatis源码解析,一步一步从浅入深(五):mapper节点的解析文章的最后部分,我们提到了动态代理的概念,下面我们就简单了解一下动态代理. 一,概念 代理设计模式的目的就是在不直接操作对象的前 ...

  3. 设计模式--适配器(Adapter)模式

    今天学习另一个设计模式,适配器(Adapter)模式,这是一个共同方向,但有特殊要求,就应用到此设计模式.写到这里,想起很久以前,有写过一篇<ASP.NET的适配器设计模式(Adapter)&g ...

  4. JAVA设计模式-动态代理(Proxy)源码分析

    在文章:JAVA设计模式-动态代理(Proxy)示例及说明中,为动态代理设计模式举了一个小小的例子,那么这篇文章就来分析一下源码的实现. 一,Proxy.newProxyInstance方法 @Cal ...

  5. Head First 设计模式 —— 13. 代理 (Proxy) 模式

    思考题 如何设计一个支持远程方法调用的系统?你要怎样才能让开发人员不用写太多代码?让远程调用看起来像本地调用一样,毫无瑕疵? P435 已经接触过 RPC 了,所以就很容易知道具体流程:客户端调用目标 ...

  6. 2、适配器 adapter 模式 加个"适配器" 以便于复用 结构型设计模式

    1.什么是适配器模式? 适配器如同一个常见的变压器,也如同电脑的变压器和插线板之间的电源连接线,他们虽然都是3相的,但是电脑后面的插孔却不能直接插到插线板上. 如果想让额定工作电压是直流12伏特的笔记 ...

  7. 设计模式C++描述----06.适配器(Adapter)模式

    一. 定义 适配器模式将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类可以一起工作. Adapter 模式的两种类别:类模式和对象模式. 二. 举例说明 实际中 ...

  8. 漫谈设计模式(二):单例(Singleton)模式

    1.前言 实际业务中,大多业务类只需要一个对象就能完成所有工作,另外再创建其他对象就显得浪费内存空间了,例如web开发中的servlet,这时便要用到单例模式,就如其名一样,此模式使某个类只能生成唯一 ...

  9. java演示适配器(adapter)模式

    为什么要使用模式: 模式是一种做事的一种方法,也即实现某个目标的途径,或者技术. adapter模式的宗旨就是,保留现有类所提供的服务,向客户提供接口,以满足客户的需求. 类适配器:客户端定义了接口并 ...

随机推荐

  1. 【剑指Offer】面试题22. 链表中倒数第k个节点

    题目 输入一个链表,输出该链表中倒数第k个节点.为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点.例如,一个链表有6个节点,从头节点开始,它们的值依次是1.2.3.4.5.6. ...

  2. java嵌套循环练习

    打印一个等腰三角形 package com.lv.jj; import java.util.Scanner; public class DemoDy { public static void main ...

  3. C++的vector容器清空

    c++内部STL库中自带了一个容器vetcor, 自带了清空方法——clear().但是clear使用之后,并不能清空数据,其数据再未被覆盖之前是不会改变的,个人猜测clear仅仅把指针挪动到了起始位 ...

  4. jQuery琐碎

    函数(以click事件为例)在jsp页面和js中的不同写法 onclick="getInfo(this);" function getInfo(obj){ var $this=$( ...

  5. mongodb replication set 主从切换

    今天被问到mongodb副本集主从切换的问题,然后发现没有相关命令的中文文档,这里翻译记录一下 rs.stepDown() rs.stepDown(stepDownSecs, secondaryCat ...

  6. PythonTwo

    格式化输出: % 占位符  s(str 字符串) d(digit 数字)  %% 只单纯显示% Str 索引切片 captlze  首字母大写 upper 全大写 lower 全小写 find 通过元 ...

  7. python3.7使用etree遇到的问题

    使用python3.6时安装好lxml时按照许多网上的教程来引入会发现etree没被引入进来 解决办法: 一.import lxml.htmletree = lxml.html.etree这样就可以使 ...

  8. 04-String——课后作业1:字串加密

    题目:请编写一个程序,加密或解密用户输入的英文字串要求设计思想.程序流程图.源代码.结果截图. 程序设计思想:首先由用户选择是加密还是解密,利用String类中的charAt函数依次取出字串中的字符, ...

  9. 【分类问题中模型的性能度量(二)】超强整理,超详细解析,一文彻底搞懂ROC、AUC

    文章目录 1.背景 2.ROC曲线 2.1 ROC名称溯源(选看) 2.2 ROC曲线的绘制 3.AUC(Area Under ROC Curve) 3.1 AUC来历 3.2 AUC几何意义 3.3 ...

  10. Failed to connect to raw.githubusercontent.com port 443: Connection refused

    问题:macOS安装Homebrew时总是报错(Failed to connect to raw.githubusercontent.com port 443: Connection refused) ...