设计模式
FTPClient与commons-pool2整合过程中涉及到的设计模式有:工厂方法模式、单例模式。
工厂方法模式
工厂方法模式定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个,工厂方法让实例化推迟到子类。当需要增加一个新的产品时,只需要增加一个具体的产品类和与之对应的具体工厂即可,无须修改原有系统。但是由于每新增一个新产品时就需要增加两个类,这样会导致系统的复杂度增加。
详细信息见:工厂模式
单例模式
单例模式确保一个类只有一个实例,并提供一个全局访问点。
单例模式有五种实现方法:双重校验锁、枚举、静态内部类、恶汉、懒汉。
在这里选择静态内部类。
详细信息见:单例模式
代码
主要有FTPClientFactory和FTPClientUtil两个类
使用commons-pool2
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.pool2.BasePooledObjectFactory;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.impl.DefaultPooledObject;
import java.util.Properties;
/**
* Created by udbwcso on 2016/3/14.
*/
public class FTPClientFactory extends BasePooledObjectFactory<FTPClient> {
private final String host;
private final int port;
private final String username;
private final String password;
public FTPClientFactory(final String host, final int port, final String username, final String password){
this.host = host;
this.port = port;
this.username = username;
this.password = password;
}
public FTPClientFactory(Properties properties){
this.host = properties.getProperty("host");
this.port = Integer.parseInt(properties.getProperty("port"));
this.username = properties.getProperty("username");
this.password = properties.getProperty("password");
}
/**
* Creates an object instance, to be wrapped in a {@link PooledObject}.
* <p>This method <strong>must</strong> support concurrent, multi-threaded
* activation.</p>
*
* @return an instance to be served by the pool
* @throws Exception if there is a problem creating a new instance,
* this will be propagated to the code requesting an object.
*/
public FTPClient create() throws Exception {
FTPClient client = new FTPClient();
client.connect(host, port);
client.login(username, password);
return client;
}
/**
* Wrap the provided instance with an implementation of
* {@link PooledObject}.
*
* @param obj the instance to wrap
* @return The provided instance, wrapped by a {@link PooledObject}
*/
public PooledObject<FTPClient> wrap(FTPClient obj) {
return new DefaultPooledObject<FTPClient>(obj);
}
/**
* destroy object
*/
@Override
public void destroyObject(PooledObject<FTPClient> p) throws Exception {
FTPClient ftpClient = p.getObject();
ftpClient.logout();
ftpClient.disconnect();
}
}
工具类
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.pool2.ObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPool;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
/**
* Created by udbwcso on 2016/3/15.
*/
public class FTPClientUtil {
private static final String FTP_PROPERTIES = "/ftp.properties";
private FTPClientUtil(){
}
public static FTPClientUtil getInstance(){
return SingletonHolder.instance;
}
/**
* Returns the pathname of the current working directory.
* @return
*/
public String getWorkingDirectory() throws Exception {
FTPClient client = getClientPool().borrowObject();
String workingDir = client.printWorkingDirectory();
getClientPool().returnObject(client);
return workingDir;
}
private ObjectPool<FTPClient> getClientPool(){
return SingletonHolder.POOL;
}
private static class SingletonHolder {
private static final ObjectPool<FTPClient> POOL;
static {
InputStream resourceAsStream = FTPClientUtil.class.getResourceAsStream(FTP_PROPERTIES);
Properties p = null;
if (resourceAsStream != null) {
p = new Properties();
try {
p.load(resourceAsStream);
} catch (IOException e) {
} finally {
try {
resourceAsStream.close();
} catch (IOException e) {
// Ignored
}
}
}
POOL = new GenericObjectPool<FTPClient>(new FTPClientFactory(p));
}
private static FTPClientUtil instance = new FTPClientUtil();
}
}
目前只有获取工作目录的方法,有待后续开发。