Java中相同class的继承与组合
Inheritance and composition of the same class in Java
我在 github 上找到了以下代码:
public class DummySSLSocketFactory extends SSLSocketFactory {
private static final Logger LOG = LoggerFactory.getLogger(DummySSLSocketFactory.class);
private SSLSocketFactory factory;
public DummySSLSocketFactory() {
try {
SSLContext sslContext = SSLContext.getInstance("TLS");
TrustManager[] trustManagers = new TrustManager[] {new DummyTrustManager()};
sslContext.init(null, trustManagers, new java.security.SecureRandom());
factory = sslContext.getSocketFactory();
} catch (Exception e) {
throw new RuntimeCamelException("Error creating DummySSLSocketFactory: " + e.getMessage(), e);
}
}
/**
* Must provide this getDefault operation for JavaMail to be able to use this factory.
*/
public static SocketFactory getDefault() {
LOG.warn("Camel is using DummySSLSocketFactory as SSLSocketFactory (only to be used for testing purpose)");
return new DummySSLSocketFactory();
}
public String[] getDefaultCipherSuites() {
return factory.getDefaultCipherSuites();
}
public String[] getSupportedCipherSuites() {
return factory.getSupportedCipherSuites();
}
public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException {
return factory.createSocket(socket, host, port, autoClose);
}
public Socket createSocket(String host, int port) throws IOException {
return factory.createSocket(host, port);
}
public Socket createSocket(String host, int port, InetAddress localAddress, int localPort)
throws IOException {
return factory.createSocket(host, port, localAddress, localPort);
}
public Socket createSocket(InetAddress host, int port) throws IOException {
return factory.createSocket(host, port);
}
public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort)
throws IOException {
return factory.createSocket(address, port, localAddress, localPort);
}
public Socket createSocket() throws IOException {
// must have this createSocket method
return factory.createSocket();
}
}
类似的实现被广泛用于不同的项目。
我试图弄清楚同时使用继承和组合的目的是什么。看起来只要有一个 returns sslContext.getSocketFactory();
结果的工厂方法就足够了,因为它根本不扩展 class。
我不知道谁写这段代码的确切意图是什么,但在这个 classes 的组织中很明显,使用组合和继承,DummySSLSocketFactory 可以 使用在 SSLSocketFactory 中实现的受保护方法 ,甚至上面的 class 中实现的方法(使用 super)。
这是可能的,因为 DummySSLSocketFactory
引用了其父 class SSLSocketFactory
private SSLSocketFactory factory;
在 DummySSLSocketFactory 的构造函数中设置
factory = sslContext.getSocketFactory();
如果没有此参考,您将能够使用 super 访问 SSLSocketLayer,但 class 甚至更高。
这是一个常见的模式(如您所述)。
A child class 可以扩展 Class(或实现接口)以建立 "is-a" 关系。
在你的例子中,
DummySSLSocketFactory
is-a SSLSocketFactory
。
"is-a" 关系允许多态性。
child class 可能不希望完全覆盖(或实现,在接口的情况下)方法,
所以它使用组合来获得一些已经覆盖了无趣但必需的方法的东西。
为达到这个,
child class 会将对 "uninteresting" (我的术语)方法的调用转发给组合成员。
在您的示例中,原始 class SSLSocketFactory
提供 "default" 对 DummySSLSocketFactory
class.
不感兴趣的东西的实现
将调用转发给组合成员是代理模式的一种变体。它不是完整代理,因为它改变了功能。
我在 github 上找到了以下代码:
public class DummySSLSocketFactory extends SSLSocketFactory {
private static final Logger LOG = LoggerFactory.getLogger(DummySSLSocketFactory.class);
private SSLSocketFactory factory;
public DummySSLSocketFactory() {
try {
SSLContext sslContext = SSLContext.getInstance("TLS");
TrustManager[] trustManagers = new TrustManager[] {new DummyTrustManager()};
sslContext.init(null, trustManagers, new java.security.SecureRandom());
factory = sslContext.getSocketFactory();
} catch (Exception e) {
throw new RuntimeCamelException("Error creating DummySSLSocketFactory: " + e.getMessage(), e);
}
}
/**
* Must provide this getDefault operation for JavaMail to be able to use this factory.
*/
public static SocketFactory getDefault() {
LOG.warn("Camel is using DummySSLSocketFactory as SSLSocketFactory (only to be used for testing purpose)");
return new DummySSLSocketFactory();
}
public String[] getDefaultCipherSuites() {
return factory.getDefaultCipherSuites();
}
public String[] getSupportedCipherSuites() {
return factory.getSupportedCipherSuites();
}
public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException {
return factory.createSocket(socket, host, port, autoClose);
}
public Socket createSocket(String host, int port) throws IOException {
return factory.createSocket(host, port);
}
public Socket createSocket(String host, int port, InetAddress localAddress, int localPort)
throws IOException {
return factory.createSocket(host, port, localAddress, localPort);
}
public Socket createSocket(InetAddress host, int port) throws IOException {
return factory.createSocket(host, port);
}
public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort)
throws IOException {
return factory.createSocket(address, port, localAddress, localPort);
}
public Socket createSocket() throws IOException {
// must have this createSocket method
return factory.createSocket();
}
}
类似的实现被广泛用于不同的项目。
我试图弄清楚同时使用继承和组合的目的是什么。看起来只要有一个 returns sslContext.getSocketFactory();
结果的工厂方法就足够了,因为它根本不扩展 class。
我不知道谁写这段代码的确切意图是什么,但在这个 classes 的组织中很明显,使用组合和继承,DummySSLSocketFactory 可以 使用在 SSLSocketFactory 中实现的受保护方法 ,甚至上面的 class 中实现的方法(使用 super)。
这是可能的,因为 DummySSLSocketFactory
引用了其父 class SSLSocketFactory
private SSLSocketFactory factory;
在 DummySSLSocketFactory 的构造函数中设置
factory = sslContext.getSocketFactory();
如果没有此参考,您将能够使用 super 访问 SSLSocketLayer,但 class 甚至更高。
这是一个常见的模式(如您所述)。
A child class 可以扩展 Class(或实现接口)以建立 "is-a" 关系。
在你的例子中,
DummySSLSocketFactory
is-a SSLSocketFactory
。
"is-a" 关系允许多态性。
child class 可能不希望完全覆盖(或实现,在接口的情况下)方法,
所以它使用组合来获得一些已经覆盖了无趣但必需的方法的东西。
为达到这个,
child class 会将对 "uninteresting" (我的术语)方法的调用转发给组合成员。
在您的示例中,原始 class SSLSocketFactory
提供 "default" 对 DummySSLSocketFactory
class.
将调用转发给组合成员是代理模式的一种变体。它不是完整代理,因为它改变了功能。