引入模板模式重构FtpClientUtil

《ftp上传与下载》文章中,封装一个Ftp上传下载的工具类,主要代码如下:

上传:

/**上传文件
	 * @param remoteFileName 远程文件名称
	 * @param locaFileName 本地文件名称
	 */
	public void upload(String remoteFileName,String locaFileName){
		FTPClient ftp=null;
		try {
			ftp = new FTPClient();
			ftp.addProtocolCommandListener( new PrintCommandListener( new PrintWriter( System.out ), true ) );
			//连接ftp服务器
			connect( ftp );
			//设置属性
			setProperty( ftp );
			//上传文件
			upload( ftp, remoteFileName, locaFileName );
			//退出
			logout( ftp );
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			if (ftp.isConnected()) {
				try {
					ftp.disconnect();
				} catch (IOException f) {
				}
			}
		}

	}

下载:

/**下载文件
	 * @param remoteFileName 远程文件名称
	 * @param locaFileName 本地文件名称
	 */
	public void download(String remoteFileName,String locaFileName){
		FTPClient ftp=null;
		try {
			ftp = new FTPClient();
			ftp.addProtocolCommandListener( new PrintCommandListener( new PrintWriter( System.out ), true ) );
			//连接ftp服务器
			connect( ftp );
			//设置属性
			setProperty( ftp );
			//下载文件
			download( ftp, remoteFileName, locaFileName );
			//退出
			logout( ftp );
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			if (ftp.isConnected()) {
				try {
					ftp.disconnect();
				} catch (IOException f) {
				}
			}
		}
	}

从上面两个方法来看,我们发现upload()与download()方法的,有公共的操作流程:

connect()

setProperty()

具体操作方法

logout( )

这时,可以使用模板模式对它进行重构,不了解模板模式的朋友,可以参考《行为模式之Template(模板模式)》

定义一个模板方法,来完成操作流程的调用,在上篇模版模式当中,是以继承的方式,由子类来实现具体的操作方法,

这次将以聚合的方式实现.

首先,将具体操作方法定义在接口中,接口定义如下:

FtpInvoke

package com.demo.ftp;

import org.apache.commons.net.ftp.FTPClient;

/**ftp操作
 * @author wobendiankun
 *2015-1-22 下午08:27:12
 */
public interface FtpInvoke {
	/**
	 * @param ftp
	 * @param remoteFileName
	 * @param locaFileName
	 */
	void doHandle(FTPClient ftp ,String remoteFileName, String locaFileName) throws Exception;
}

其次,引入一个新的模版类,名为FtpTemplate,定义一个模板方法handle(),如下:

private void handle(FtpInvoke ftpInvoke, String remoteFileName,
			String locaFileName) {
		FTPClient ftp = null;
		try {
			ftp = new FTPClient();
			ftp.addProtocolCommandListener(new PrintCommandListener(
					new PrintWriter(System.out), true));
			// 连接ftp服务器
			connect(ftp);
			// 设置属性
			setProperty(ftp);
			// 具体操作方法
			ftpInvoke.doHandle(ftp, remoteFileName, locaFileName);
			// 退出
			logout(ftp);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (ftp.isConnected()) {
				try {
					ftp.disconnect();
				} catch (IOException f) {
				}
			}
		}
	}

接着,修改相关的操作方法,upload()及download()方法,利用一个匿名类,让handle()方法来回调

/**
	 * 上传文件
	 *
	 * @param remoteFileName
	 *            远程文件名称
	 * @param locaFileName
	 *            本地文件名称
	 */
	public void upload(String remoteFileName, String locaFileName) {
		handle(new FtpInvoke() {

			@Override
			public void doHandle(FTPClient ftp, String remoteFileName,
					String locaFileName) throws Exception {
				//上传文件
				upload( ftp, remoteFileName, locaFileName );
			}
		}, remoteFileName, locaFileName);

	}
/**
	 * 下载文件
	 *
	 * @param remoteFileName
	 *            远程文件名称
	 * @param locaFileName
	 *            本地文件名称
	 */
	public void download(String remoteFileName, String locaFileName) {
		handle(new FtpInvoke() {

			@Override
			public void doHandle(FTPClient ftp, String remoteFileName,
					String locaFileName) throws Exception {
				// 下载文件
				download(ftp, remoteFileName, locaFileName);
			}
		}, remoteFileName, locaFileName);
	}

最后要让FtpClientUtil聚合FtpTemplate,然后将对应的请求委托给FtpTemplate来处理就可以了,大功告成.

package com.demo.ftp;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ConnectException;

import org.apache.commons.net.PrintCommandListener;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;

/**
 * @author wobendiankun 2015-1-8 下午08:11:08
 */
public class FtpClientUtil {
	FtpTemplate fpFtpTemplate ;

	public FtpClientUtil () {
		String server = "localhost";
		int port = 21;
		String username = "kun";
		String password = "111111";
		fpFtpTemplate = new FtpTemplate(server, port, username, password);
	}

	public FtpClientUtil(String server, int port, String username,
			String password) {
		fpFtpTemplate = new FtpTemplate(server, port, username, password);
	}
	/**上传文件
	 * @param remoteFileName 远程文件名称
	 * @param locaFileName 本地文件名称
	 */
	public void upload(String remoteFileName,String locaFileName){
		fpFtpTemplate.upload(remoteFileName, locaFileName);
	}
	/**下载文件
	 * @param remoteFileName 远程文件名称
	 * @param locaFileName 本地文件名称
	 */
	public void download(String remoteFileName,String locaFileName){
		fpFtpTemplate.download(remoteFileName, locaFileName);
	}
	/**创建文件夹
	 * @param remotePathName 远程文件夹名称
	 */
	public void mkdir(String remotePathName) {
		fpFtpTemplate.mkdir(remotePathName);
	}

}

FtpInvoke:

package com.demo.ftp;

import org.apache.commons.net.ftp.FTPClient;

/**ftp操作
 * @author wobendiankun
 *2015-1-22 下午08:27:12
 */
public interface FtpInvoke {
	/**
	 * @param ftp
	 * @param remoteFileName
	 * @param locaFileName
	 */
	void doHandle(FTPClient ftp ,String remoteFileName, String locaFileName) throws Exception;
}

FtpTemplate

package com.demo.ftp;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ConnectException;

import org.apache.commons.net.PrintCommandListener;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;

/**
 * @author wobendiankun 2015-1-22 下午08:27:46
 */
public class FtpTemplate {
	/**
	 * ftp服务器地址
	 */
	private String server;
	/**
	 * 端口
	 */
	private int port;
	/**
	 * 用户名
	 */
	private String username;
	/**
	 * 密码
	 */
	private String password;

	public FtpTemplate(String server, int port, String username, String password) {
		this.server = server;
		this.port = port;
		this.username = username;
		this.password = password;
	}

	/**
	 * @param ftp
	 */
	private void connect(FTPClient ftp) throws Exception {
		// 连接服务器
		ftp.connect(server, port);
		int reply = ftp.getReplyCode();
		// 是否连接成功
		if (!FTPReply.isPositiveCompletion(reply)) {
			throw new ConnectException(server + " 服务器拒绝连接");
		}
		// 登陆
		if (!ftp.login(username, password)) {
			throw new ConnectException("用户名或密码错误");
		}
	}

	/**
	 * @param ftp
	 * @throws Exception
	 */
	private void setProperty(FTPClient ftp) throws Exception {
		ftp.enterLocalPassiveMode();
		// 二进制传输,默认为ASCII
		ftp.setFileType(FTP.BINARY_FILE_TYPE);
	}

	/**
	 * @param ftp
	 */
	private void logout(FTPClient ftp) throws Exception {
		ftp.noop();
		ftp.logout();
	}
	/**
	 * @param ftp
	 * @param remoteFileName
	 * @param locaFileName
	 */
	private void upload(FTPClient ftp, String remoteFileName,
			String locaFileName) throws Exception{
		//上传
		InputStream input;

		input = new FileInputStream(locaFileName);

		ftp.storeFile(remoteFileName, input);

		input.close();
	}

	/**
	 * @param ftp
	 * @param remoteFileName
	 * @param locaFileName
	 */
	private void download(FTPClient ftp, String remoteFileName,
			String locaFileName) throws Exception {
		OutputStream output = null;
		output = new FileOutputStream(locaFileName);
		ftp.retrieveFile(remoteFileName, output);
		output.close();
	}
	/**
	 * @param ftp
	 * @param remotePathName
	 */
	private void mkdir(FTPClient ftp, String remotePathName) throws Exception{
		ftp.makeDirectory(remotePathName);
	}

	private void handle(FtpInvoke ftpInvoke, String remoteFileName,
			String locaFileName) {
		FTPClient ftp = null;
		try {
			ftp = new FTPClient();
			ftp.addProtocolCommandListener(new PrintCommandListener(
					new PrintWriter(System.out), true));
			// 连接ftp服务器
			connect(ftp);
			// 设置属性
			setProperty(ftp);
			// 具体操作方法
			ftpInvoke.doHandle(ftp, remoteFileName, locaFileName);
			// 退出
			logout(ftp);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (ftp.isConnected()) {
				try {
					ftp.disconnect();
				} catch (IOException f) {
				}
			}
		}
	}

	/**
	 * 上传文件
	 *
	 * @param remoteFileName
	 *            远程文件名称
	 * @param locaFileName
	 *            本地文件名称
	 */
	public void upload(String remoteFileName, String locaFileName) {
		handle(new FtpInvoke() {

			@Override
			public void doHandle(FTPClient ftp, String remoteFileName,
					String locaFileName) throws Exception {
				//上传文件
				upload( ftp, remoteFileName, locaFileName );
			}
		}, remoteFileName, locaFileName);

	}

	/**
	 * 下载文件
	 *
	 * @param remoteFileName
	 *            远程文件名称
	 * @param locaFileName
	 *            本地文件名称
	 */
	public void download(String remoteFileName, String locaFileName) {
		handle(new FtpInvoke() {

			@Override
			public void doHandle(FTPClient ftp, String remoteFileName,
					String locaFileName) throws Exception {
				// 下载文件
				download(ftp, remoteFileName, locaFileName);
			}
		}, remoteFileName, locaFileName);
	}

	/**创建文件夹
	 * @param remotePathName 远程文件夹名称
	 */
	public void mkdir(String remotePathName) {
		handle(new FtpInvoke() {

			@Override
			public void doHandle(FTPClient ftp, String remoteFileName,
					String locaFileName) throws Exception {
				//创建文件夹
				mkdir( ftp, remoteFileName);
			}
		}, remotePathName, null);
	}
}
时间: 2024-10-01 05:39:45

引入模板模式重构FtpClientUtil的相关文章

模板模式和适配器模式

一.模板模式 1.模板模式(Template Method pattern):指定义一个算法的骨架,并允许子类为一个或者多个步骤提供实现.模板方法使得子类可以在不改变算法结构的情况下,重新定义算法的某些步骤.(属于行为型模式) 2.适用场景 一次性实现一个算法的不变的部分,并将可变的行为留给子类来实现 各子类中公共的行为被提取出来并集中到一个公共的父类中,从而避免代码重复 3.优点 提高代码的复用性 提高代码的扩展性 符合开闭原则 4.缺点 类数目的增加 间接地增加了系统实现的复杂度 继承关系自

重构_使用模板模式替代重复业务操作

在日常开发中经常有重复的业务操作,每次写这些重复操作时总感觉冗余,又少点管理.今天我在开发中又遇到了这个问题,却发现项目组中的大牛已经帮我将重复的操作管理好了,于是便请教一番,偷偷学了这个---模板设计模式. 模板设计模式要注意以下几点: 将重复的业务操作抽取出一套模板: 将实现模板的实现类放到管理器中统一管理: 在业务中用的时候只用管理器,忽略模板的实现类. 掌握了要点之后,我们开始今天的实战阶段,项目中的需求是这样的: 先找到有某一类型的货品的日志表,日志表有,货品与日志表的对应关系也有(货

《Java8实战》 - 8.2.2 使用 Lambda 重构面向对象的设计模式 之 模板模式

模板模式是啥? 一个抽象类Template主类,充分发挥抽象类的作用,一部分方法定义好,另一部分以接口的形式体现--需要每个子类具体地进行实现. 适用栗子: 造房子的时候,地基.走线.水暖.水管都是一样的,只有在建筑的后期才需要加自定义的冰箱.电视机.热水器等,自定义的部分交给住户自己实现决定. 西游记的九九八十一难,唐僧四人必须一个不漏地走完,这就是固定部分的模板:除了菩萨定好的,途中的支线任务,这部分菩萨只写了接口,唐僧四人组完全可以自由发挥,选择不同的具体实现. spring 中对 Hib

设计模式之 - 模板模式(Template Pattern)

引入:这几天在看一本讲spring源码的书<SPRING技术内幕>里面在讲加载配置文件的时候,可以有不同的加载方式,如根据文件系统目录加载配置文件(FileSystemXmlApplicationContext),类路径加载配置文件(ClassPathXmlApplicationContext),以及根据项目上下文目录(XmlWebApplicationContext)加载配置文件.这个在加载的过程中就使用了模板设计模式,所以就来学习下模板设计模式. 1. 模板设计模式在书中定义:  定义一个

行为模式之Template(模板模式)

模板模式定义一系列的操作流程,并将其中的一个或多个操作的实现延迟到子类之中. 我们以牛奶加工过程为例,当然对其做了简化,具体流程如下图: 首先,将加工过程定义成一个抽象类: AbstractMilkProcess package com.design; /**牛奶加工过程 * @author wobendiankun *2015-1-21 下午08:01:57 */ public abstract class AbstractMilkProcess { /** *挤奶 */ protected

设计模式——模板模式

模板模式: 准备一个抽象类,讲部分逻辑以具体方法的形式实现,然后声明一些抽象方法交由子类实现剩余逻辑,用钩子方法给予子类更大的灵活性.最后将方法汇总构成一个不可改变的模板方法. 适用场景 1 算法或操作遵循相似的逻辑 2 重构时(把相同的代码抽取到分类) 优势: 1 封装性好 2 复用性好 3 疲敝细节 4 便于维护 缺点 1   继承 源码: RefreshBeverage package com.imooc.pattern.template; /**  * 抽象基类,为所有的子类提供一个算法

mvc理念和thinkphp的语法特征 thinkphp引入模板

mvc即模型(model)-视图(view)-控制器(controller)的缩写 控制器很重要,功能性的东西要靠它实现,模型我还没接触到,只知道它对数据库负责,类似一个大控件吧... 速度... 一个网站说白了还是给用户看的视图,那么控制器可以控制视图... 控制器在D:\WWW\myapp\Index\Lib\Action里面 入口文件是index.php <?php define('APP_NAME','Index'); //项目名称 define('APP_PATH','./Index/

Android开发之模板模式初探

模板模式我认为在Android的开发中是最长用到的,基本是随处可见的,认识该模式,有助于我们对Android的源代码及框架有一个更深层次的认识.那什么是模板模式呢,模板模式就是定义一个基本框架,将当中的一些方法延迟到子类中运行实现.就比方我们去餐馆吃饭,基本步骤肯定为找到座位,点菜,上菜,吃饭,买单五个过程,当中点菜这个过程是可变的,我们点的菜可多可少,其它都是固定的,那么我们就能够写在一个固定的抽象类里形成一个基本框架,我们的子类继承该抽象类,对当中可变的方法进行复写. 以下我们就来看一个样例

模板模式(Template Pattern)

引入:这几天在看一本讲spring源码的书<SPRING技术内幕>里面在讲加载配置文件的时候,可以有不同的加载方式,如根据文件系统目录加载配置文件(FileSystemXmlApplicationContext),类路径加载配置文件(ClassPathXmlApplicationContext),以及根据项目上下文目录(XmlWebApplicationContext)加载配置文件.这个在加载的过程中就使用了模板设计模式,所以就来学习下模板设计模式. 1. 模板设计模式在书中定义:  定义一个