简体   繁体   中英

Inheritance and composition of the same class in Java

I have found following piece of code on 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();
    }

}

Similar implementations are widely used across different projects. I tried to figure out what is the purpose of using both inheritance and composition at the same time. It looks like it would be enough just to have a factory method that returns the result of sslContext.getSocketFactory(); as it doesn't extend the class at all.

I don't know what was the precise intent of who wrote this code, but in this organization of classes is clear that using both composition and inheritance, DummySSLSocketFactory can use protected methods implemented in SSLSocketFactory and even of the class above to it (using super).
This is possible because DummySSLSocketFactory has a reference to its parent class SSLSocketFactory

 private SSLSocketFactory factory;

set in DummySSLSocketFactory's costructor

factory = sslContext.getSocketFactory();

Without this reference you would be able to reach SSLSocketLayer using super, but not the class even higher.

This is a common pattern (as you mentioned).

A child class can extend a Class (or implement an Interface) to establish a "is-a" relationship. In your example, DummySSLSocketFactory is-a SSLSocketFactory . An "is-a" relationship allows polymorphism.

The child class may not wish to fully override (or implement, in the case of an Interface) the methods, so it uses composition to get something that already overrides the uninteresting, but required, methods. To achieve this, the child class will forward calls to the "uninteresting" (my term there) methods to the composed member. In your example, the original class SSLSocketFactory provides the "default" implementation of stuff that is not interesting to the DummySSLSocketFactory class.

The forwarding of calls to the composed member is a variation of the Proxy pattern. It is not a full proxy, because it alters the functionality.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM