Android源码中的设计模式之工厂方法

       工厂方法属于设计模式中抽象工厂的一部分,在Android源码中用的比较多,所以单独拿出来讨论。 结合源码中的几个例子,稍加分析,加深自己对工厂方法的理解。

定义

        工厂方法模式定义了一个创建对象的接口,由子类决定具体实例化的类是哪一个。关于让子类决定的含义,指的是父类中做了定义,但是具体实现是在子类中。“决定”并不是指模式允许子类本身运行时做决定,而是指编写创建类时,不需要知道实际创建的产品是哪一个,父类选择了使用哪个子类,自然就决定了实际创建的产品是什么。

UML类图

源码中的工厂方法

Socket/SocketFactory/SSLSocket/SSLSocketFactory

前面的UML类图是根据Socket/SocketFactory画的,下面是他们的源码(已省略注释和其他不相关的方法):

SocketFactory.java

1
2
3
4

public interface SocketFactory {
Socket createSocket() throws IOException;
}

SSLSocketFactory.java

1
2
3
4
5
6
7
8
9
10

public class SSLSocketFactory implements LayeredSocketFactory {

public Socket createSocket(final Socket socket, final String host, final int port, final boolean autoClose) throws IOException, UnknownHostException {
SSLSocket sslSocket = (SSLSocket) this.socketfactory.createSocket(socket, host, port, autoClose);
sslSocket.startHandshake();
hostnameVerifier.verify(host, sslSocket);
return sslSocket;
}
}

LayeredSocketFactory继承自SocketFactory,这里为了代码结构简单一点,做了省略。

        可能有人不熟悉Socket,这里简单介绍下,Socket两个主机之间的连接,他们之间可以通过Socket收发数据。像目前经常用到的HttpUrlConnection,就是基于Socket封装的。SSLSocket通信是对Socket通信的的拓展,在Socket通信的基础上添加了一层安全性保护,提供了更高的安全性,包括身份验证、数据加密以及完整性验证。

        在工厂方法模式中,SocketFactory是创建者接口,他定义了一个工厂方法createSocket(),让子类实现此方法创建产品Socket。SSLSocketFactory实现SocketFactory接口,重写createSocket()方法创建SSLSocket。

Calendar

Calendar.java

1
2
3
4

public static Calendar getInstance() {
return createCalendar(TimeZone.getDefault(), Locale.getDefault(Locale.Category.FORMAT));
}

getInstance()是静态工厂方法,可以在方法内创建对象,封装一些预处理。通过{类.方法}调用,如Calendar.getInstance();

工厂方法的优点

增加代码复用性

        在createSocket()方法中封装了获取SSLSocket对象,启动握手和请求地址验证等操作,如果不用工厂方法,每次在创建SSLSocket的时候都要做这些操作,假设项目中有5个地方要用到SSLSocket,可以想象多出来的代码有多少? 另外,如果将来增加SSLSocket新特性,只要改动SSLSocketFactory中创建代码部分,其他模块完全可以不用动。

降低耦合性

        一般情况下,我们都是通过 new 的方式创建对象,这么做带来的问题是-创建对象的代码和对象耦合性增高,什么意思呢?假设某个业务逻辑发生变动,对象要做出改动,那么实际上改动的地方不止一处,使用该对象的地方都要受影响,这就是高耦合带来的烦恼。工厂方法恰恰是减少这种烦恼,因为工厂方法是在一处创建对象,即使对象变动,要改动的地方也仅仅是工厂方法创建对象的部分。

基于超类编程

在实际使用的时候,我们一般会这样做:

1
2
3
4
5

Socket socket = SSLSocketFactory.getDefault().createSocket(xx,xx);

// socket相关操作
...

因为createSocket()在父类或者接口中已经定义好返回类型,所以将来换作其他Socket的时候,直接替换工厂对象和修改参数部分,比如这样:

1
2
3
4
5

Socket socket = XXXSocketFactory.getDefault().createSocket(xx,xx);

// socket相关操作
...

至于socket后续操作,基本不会改动太多,甚至说没有改动。

结束语

        好了,关于工厂方法模式的内容就先讨论到这,如果有哪些地方不明白的童鞋可以留言,我们一起探讨。所有的设计模式中,工厂方法在Android源码中用的相对比较多的,也是最容易理解的,后续我还会出其他几个常用模式的博客,希望大家能喜欢。