Java 委托机制

2021/04/03 Java高级知识 共 3525 字,约 11 分钟
闷骚的程序员

1. 委托机制

1.1 什么是委托机制?

A类持有B对象,外部程序调用A的某个方法,A再委托B去处理。
这种基于水平扩展A对象功能的方式,就称为java中的委托机制。
一般来讲,如何让A对象持有B对象的引用,存在两种常见方式:

  1. 通过外部注入的方式,即外部向A对象注入B对象。
  2. 通过内建的方式,即A对象自己完成B对象的实例化和初始化过程。

同样,B对象在A对象中以什么身份存在,也分为两种:

  1. B对象作为A对象的成员变量存在。
  2. B对象作为A对象的方法变量存在。

那实际上,上面组合下,即得出,让A对象持有B对象的引用,共有4种方式:

  1. A类中定义一个B类型的成员,以成员变量的方式接收B对象,外部向A类注入B对象,即以成员变量的方式注入B对象。
  2. A类中定义一个B类型的成员,以成员变量的方式接收B对象,A类自己实例化B对象,即以成员变量的方式内建B对象。
  3. A类中定义一个B类型的局部成员,以局部成员的方式接收B对象,在调用A类某个方法时,定义一个形式参数用来注入B对象,即以局部变量的方式注入B对象。
  4. A类中定义一个B类型的局部成员,以局部成员的方式接收B对象,在调用A类某个方法时,A类自己负责实例化B对象,即以局部变量的方式内建B对象。

tips:
委托机制的4种方式中,注入的方式用的比较多,内建的方式用的比较少。
因为注入的方式完全由程序外部进行控制,而内建的方式由成员内部直接固化,灵活度比较低,可扩展性不高。
并且作为成员变量被外部注入的方式尤其使用的最多,像spring中牛逼哄哄的依赖注入,实际上就是外部向目标bean注入成员变量。
在这里很有必要对外部注入成员变量的方式细分下,常见的具体注入成员变量的操作有两种:

  1. 外部直接通过构造方法向目标类注入成员变量,这要求目标类存在有参构造。
  2. 外部直接通过setter方法向目标类注入成员变量,这要求目标类存在setter方法。

2. 委托机制的实现方式

2.1 以成员变量的方式注入

ClassA:

package zeh.test.demo.com.call.back.weituo.waibu;

public class ClassA {
    // 使用成员变量的方式接收外部的注入
    private ClassB classB;
    // 直接提供有参构造器的方式,暴露给客户端以便注入成员
    public ClassA(ClassB classB) {
        this.classB = classB;
    }
    // 也可以提供对应的setter方法,暴露给客户端以便注入成员,它和构造方法的方式二选一即可
    public void setClassB(ClassB classB){
        this.classB = classB;
    }
    public void testClassA() {
        System.out.println("classA begin");
        classB.testClassB();
        System.out.println("classA end");
    }
}

ClassB:

package zeh.test.demo.com.call.back.weituo.waibu;

public class ClassB {
    public void testClassB() {
        System.out.println("classB 提供的核心功能...");
    }
}

TestWaiBu:

package zeh.test.demo.com.call.back.weituo.waibu;

public class TestWaiBu {
    public static void main(String[] args) {
        // 以成员变量的方式注入B对象
        ClassB classB = new ClassB();
        // 通过有参构造的方式注入外部成员classB
        ClassA classA = new ClassA(classB);
        classA.testClassA();
        // 通过setter方法注入外部成员classB
        classA = new ClassA(null);
        classA.setClassB(classB);
        classA.testClassA();
    }
}

2.2 以成员变量的方式内建

ClassA:

package zeh.test.demo.com.call.back.weituo.neibu;

public class ClassA {
    // 使用成员变量的方式,直接内建一个B对象
    private ClassB classB = new ClassB();
    public void testClassA() {
        System.out.println("classA begin");
        classB.testClassB();
        System.out.println("classA end");
    }
}

ClassB:

package zeh.test.demo.com.call.back.weituo.neibu;

public class ClassB {
    public void testClassB() {
        System.out.println("classB 提供的核心功能...");
    }
}

TestNeiBu:

package zeh.test.demo.com.call.back.weituo.neibu;

public class TestNeiBu {
    public static void main(String[] args) {
        // 不用向A注入B对象,A内部已经内建了B对象
        ClassA classA = new ClassA();
        classA.testClassA();
    }
}

2.3 以局部变量的方式注入

ClassA:

package zeh.test.demo.com.call.back.weituo.waibu;

public class ClassA {
    // 定义局部变量 classB,用于接收外部的注入
    public void testClassA(ClassB classB) {
        System.out.println("classA begin");
        classB.testClassB();
        System.out.println("classA end");
    }
}

ClassB:

package zeh.test.demo.com.call.back.weituo.waibu;

public class ClassB {
    public void testClassB() {
        System.out.println("classB 提供的核心功能...");
    }
}

TestNeiBu:

package zeh.test.demo.com.call.back.weituo.waibu;

public class TestWaiBu {
    public static void main(String[] args) {
        // 以局部变量的方式注入B对象
        ClassB classB = new ClassB();
        ClassA classA = new ClassA();
        classA.testClassA(classB);
    }
}

2.4 以局部变量的方式内建

ClassA:

package zeh.test.demo.com.call.back.weituo.neibu;

public class ClassA {
    public void testClassA() {
        System.out.println("classA begin");
        // 使用局部变量的方式,直接内建一个B对象
        ClassB classB = new ClassB();
        classB.testClassB();
        System.out.println("classA end");
    }
}

ClassB:

package zeh.test.demo.com.call.back.weituo.neibu;

public class ClassB {
    public void testClassB() {
        System.out.println("classB 提供的核心功能...");
    }
}

TestNeiBu:

package zeh.test.demo.com.call.back.weituo.neibu;

public class TestNeiBu {
    public static void main(String[] args) {
        // 不用向A注入B对象,A内部已经内建了B对象
        ClassA classA = new ClassA();
        classA.testClassA();
    }
}

3. 总结

委托机制是一种机制,是一种底层的思想。
很多设计模式或者设计理念都依赖委托机制,像方法转发、回调机制、钩子模式、代理设计模式、装饰者模式等,其底层都依赖的是委托机制。
委托机制的核心,实际上就是多态,说白了就是引用传递在多态中的应用,即向上转型。假如没有多态的话,则每个委托类只能委托一种类型的依赖对象,就失去了委托的核心功能。

文档信息

Search

    Table of Contents