转发 (面向对象程序设计)

面向对象程序设计中，转发(forwarding)是指使用一个对象的成员（属性或方法）导致实际使用了另一个对象的对应的成员。即“转发”到另一个对象。转发被用于很多软件设计模式中，某些成员的使用被转发到别的对象，另外的成员由当前直接使用的对象使用。转发的对象可称作“包装对象）（wrapper object），显式转发的成员可称为包装函数。

与委托的区别

转发与委托在形式上是一对互补的概念。两种情况下，有2个对象，第一个（发送者、包装器）对象使用第二个（接收者、被包装者）对象，例如调用一个方法。两种情况的接收对象中的self指向不同的内容（可以理解为不同的运行时上下文）：对于委托，self指向发送者对象，对于转发，self指向接收者对象。self也常被隐式作为动态分派的一部分，即方法解析：方法名字指向了哪个函数。

委托类似于继承，允许行为复用(具体说代码复用)，转发类似于，执行仅依赖于接收者对象。两种情况，复用是动态的，在运行时确定其内容（基于委托或者转发到哪个对象）,而不是静态的（编译、链接时确定哪个类被“继承”）。

例子
Java的显式转发的例子：B的实例转发foo方法的调用给它的字段a:

class B {
    A a;
    T foo() { return a.foo(); }
}
当执行a.foo(), this对象是a (A的子类型), 不是最初对象的(B的实例)。进一步，a不必是A的实例，也可是其子类型的实例。甚至A不是一个类，而是接口/协议。

与继承相比较，foo定义于超类A中（必须是类，不能是接口），在子类B中调用方法，使用A中定义的代码，但this对象仍然是B的实例:
class A {
    T foo() { /* ... */ };
}

class B extends A {
}

下述Python例子，类B转发foo方法调用和属性x到它的字段a的对象：

class A:
    def __init__(self, x) -> None:
        self.x = x

    def foo(self):
        print(self.x)

class B:
    def __init__(self, a) -> None:
        self.a = a

    def foo(self):
        self.a.foo()

    @property
    def x(self):
        return self.a.x

    @x.setter
    def x(self, x):
        self.a.x = x

    @x.deleter
    def x(self):
        del self.a.x

a = A(42)
b = B(a)
b.foo()  # Prints '42'.
b.x  # Has value '42'
b.x = 17   # b.a.x now has value 17
del b.x  # Deletes b.a.x.

 简单示例 
class RealPrinter { // the "receiver"
    void print() { 
        System.out.println("Hello world!"); 
    }
}

class Printer { // the "sender"
    RealPrinter p = new RealPrinter(); // create the receiver
    void print() {
        p.print(); // calls the receiver
    }
}

public class Main {
    public static void main(String[] arguments) {
        // to the outside world it looks like Printer actually prints.
        Printer printer = new Printer();
        printer.print();
    }
}

 复杂示例 
装饰模式使用接口，转发更为灵活且类型安全。下例子中，灵活是指类不需要引用类或，类C可以转发到任何实现了接口的类。 

interface I {
	void f();
	void g();
}

class A implements I {
	public void f() { System.out.println("A: doing f()"); }
	public void g() { System.out.println("A: doing g()"); }
}

class B implements I {
	public void f() { System.out.println("B: doing f()"); }
	public void g() { System.out.println("B: doing g()"); }
}

// changing the implementing object in run-time (normally done in compile time)
class C implements I {
	I i = null;
	// forwarding
	public C(I i){ setI(i); }
	public void f() { i.f(); }
	public void g() { i.g(); }

	// normal attributes
	public void setI(I i) { this.i = i; }
}

public class Main {
	public static void main(String[] arguments) {
		C c = new C(new A());
		c.f();	// output: A: doing f()
		c.g();	// output: A: doing g()
		c.setI(new B());
		c.f();	// output: B: doing f()
		c.g();	// output: B: doing g()
	}
}

应用
转发可用于许多设计模式。 Forwarding is used directly in several patterns:

 责任链模式
 装饰模式: 装饰器对象增加自己的成员，把其余成员的调用转发给被装饰对象。
 代理模式: 代理对象把对成员的使用转发给真正的对象。

转发也可以用于其他设计模式，但可能是修改过的转发：
 适配器模式
 桥接模式
 门面模式

参考文献

Category:面向对象的程序设计