DIY迷你邮件客户端的开发算是告一段落,能够从中获取的东西需要往后实践中去感受和践行了。面对开始出现的问题,没能处理好,只有在整个过程来处理和消化掉可能带来的更多问题。
思考DIY迷你客户端开发手记(一)中的5中问题才是清除掉乱七八糟的工程之后的价值了。
1.业务策略编程
在整个应用中最核心的问题是:通过选择收件人的邮件地址的源文件,加载到收件人的集合中,进而发送相应的邮件。
处理这个问题自然想到了策略模式。
先定义一个接口,声明了子类需要实现的方法,然后通过不同的需求来实现其中的功能。
编码-0:定义了解析文件中的联系人邮件地址的策略接口
- public interface AnalysisStrategy {
- /**
- *
- * 解析联系人数据源
- *
- * @return list
- */
- public List<String> analysisSrc();
- }
编码-1:主要的两种模式是,解析Excel文件和XML文件
- public class ExcelContacts implements AnalysisStrategy {
- private File excelFile;
- public ExcelContacts(File f) {
- this.excelFile = f;
- }
- /**
- * 联系人Excel表
- *
- * @help 参见规定的Excel格式
- *
- * @return list
- */
- @Override
- public List<String> analysisSrc() {
- Workbook wb = null;
- List<String> contactsList = null;
- try {
- wb = Workbook.getWorkbook(excelFile);
- Sheet[] sheets = wb.getSheets();
- contactsList = new ArrayList<String>();
- for (int i = 0, j = sheets.length; i < j; i++) {
- Cell[] cells = sheets[i].getColumn(2);
- for (int row = 1, rows = cells.length; row < rows; row++) {
- String str=cells[row].getContents().trim();
- if(MiniMailTool.checkEmail(str)){
- contactsList.add(str);
- }
- }
- }
- } catch (IOException ex) {
- Logger.getLogger(ExcelContacts.class.getName()).log(Level.SEVERE, null, ex);
- } catch (BiffException ex) {
- Logger.getLogger(ExcelContacts.class.getName()).log(Level.SEVERE, null, ex);
- }
- return contactsList;
- }
- }
- //-----------------------------------------------------//
- public class XMLContacts implements AnalysisStrategy {
- private File xmlFile;
- public XMLContacts(File f) {
- this.xmlFile=f;
- }
- /**
- * 联系人XML表
- *
- * @help 参见规定的XML格式
- *
- * @param xmlFile
- * @return list
- */
- @Override
- public List<String> analysisSrc() {
- List<String> contactsList=null;
- try {
- SAXBuilder sb =new SAXBuilder();
- Document doc=sb.build(xmlFile);
- Element root=doc.getRootElement();
- List<Element> userList=root.getChildren("user");
- contactsList=new ArrayList<String>();
- for(int i=0, j=userList.size(); i<j; i++){
- Element children=userList.get(i);
- String str=children.getChildText("email").trim();
- if(MiniMailTool.checkEmail(str)){
- contactsList.add(str);
- }
- }
- } catch (JDOMException ex) {
- Logger.getLogger(XMLContacts.class.getName()).log(Level.SEVERE, null, ex);
- } catch (IOException ex) {
- Logger.getLogger(XMLContacts.class.getName()).log(Level.SEVERE, null, ex);
- }
- return contactsList;
- }
- }
通过这样的方式就可以将不同的文件的解析联系人的过程封装掉,对于调用者来讲是相同的,只需要面向接口编程就可以了。
这里给出源文件的格式:
EXCEL表的格式
XML格式:
这里的格式可以按照已经约定的方式书写,当然亦可以自定义格式,这样就应该编写实现
AnalysisStrategy(联系人解析)接口。
2.处理一些关于字符串,邮件地址验证,获取收件人地址信息
这样的问题一般在编程开始的时候会有所考虑,倒是带来的后续问题不大,如何有效的编写更加通用的代码,才是问题的关键。
这里有个关于工具类的命名问题,比如:Utils,Tools,Helper等类的命名都是非常不可取的方式,命名要简明思议,并且能够传单一定的信息,像这个工具类处理哪方面的问题,都应该能够很好的放映出来。
工具类有可能涉及到:字符串处理方面;文件解析,文件过滤方面;图形用户界面编程中的组件信息处理方面;特定的多出使用的方法,变量等;类的构造和管理等方面。
这个应用程序设计的相关方法不是很多,较好的处理掉了。
编码-2:邮件客户端程序的工具类
- /**
- *
- * 邮件客户端程序工具类
- *
- * @author aiilive
- */
- public final class MiniMailTool {
- /**
- * 获取框架在Windows中显示的中心点
- *
- * @param jf
- * @return 中心点
- */
- public static Point getCenter(JFrame jf) {
- Point p = new Point();
- Dimension dim = jf.getSize();
- int width = dim.width;
- int height = dim.height;
- Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
- p.setLocation((screenSize.width - width) / 2, ((screenSize.height - height) / 2));
- return p;
- }
- /**
- * 通过收件人信息获取收件人
- *
- * @param contactsString
- * @return List
- */
- public static List getToContacts(String contactsText) {
- String[] contacts = contactsText.split(";");
- return Arrays.asList(contacts);
- }
- /**
- * 验证输入的联系人的电子邮箱的有效性
- *
- * @param contactsText
- * @return bo
- */
- public static boolean checkContacts(String contactsText){
- String[] contacts = contactsText.split(";");
- boolean bo=true;
- for (int i = 0; i < contacts.length; i++) {
- contacts[i] = contacts[i].trim();
- if(!checkEmail(contacts[i])){
- bo=false;
- break;
- }
- }
- return bo;
- }
- /**
- * 中文字符转换
- *
- * @param str
- * @return strEncode
- */
- public static String chineseEncode(String str) {
- String strEncode = str;
- try {
- byte[] bts = str.getBytes("ISO-8859-1");
- strEncode = new String(bts, "GB2312");
- } catch (UnsupportedEncodingException ex) {
- Logger.getLogger(MiniMailTool.class.getName()).log(Level.SEVERE, null, ex);
- }
- return strEncode;
- }
- /**
- * 将字符数组char [] 转化为字符串String
- *
- * @param ch []
- * @return String
- */
- public static String arrayToString(char[] ch) {
- if (ch == null) {
- return "null";
- }
- StringBuilder b = new StringBuilder();
- for (int i = 0; i < ch.length; i++) {
- b.append(ch[i]);
- }
- return b.toString();
- }
- /**
- * 验证电子邮件地址是否有效
- *
- * @param email 电子邮件地址字符串
- * @return 布尔值
- */
- public static boolean checkEmail(String email) {
- Pattern pattern=Pattern.compile("\\w+@(\\w+.)+[a-z]{2,3}");
- Matcher matcher=pattern.matcher(email);
- return matcher.matches();
- }
- }
上面的代码涉及到了用户界面组件的工具类方法,字符串处理,常用的验证等。对于一个较大的工程,或者是涉及相关的操作非常多和复杂的时候,就得考虑方法的组织,重构,提取,建立更好的类的层次关系这样才符合面向对象编程基本思想,才能够获得可以水平和垂直扩展的机会。同时使得代码的耦合度降到最低,想要达到如此美好的境况,又得回到设计和组织方面去。
3.用户界面的布局,各个组件在特定时间的状态
正因为有用户界面,所以考虑各组件之间的组织关系,程序运行是组件的状态。活动图虽然集中注意力的面向的是活动参与者,对于桌面应用程序而言,每一个组件正可以看作是活动的参与者,因此正确对待组件状态,就可以呈现一个真实的活动状态。
比如:在没有进行邮件信息检查时,发送按钮是禁用的;为发送邮件时,状态信息显示填写发件信息,发送完成时发送完成或者发送失败;验证收件人的电子邮件信息时;不符合格式的地址,显示相应的提示信息等等,这样都源于我们对客观的事物和感知,也是对我们的用户交互,人性化设计的要求。
本文出自 “野马红尘” 博客,谢绝转载!