DIY迷你邮件客户端开发手记(二)

  DIY迷你邮件客户端的开发算是告一段落,能够从中获取的东西需要往后实践中去感受和践行了。面对开始出现的问题,没能处理好,只有在整个过程来处理和消化掉可能带来的更多问题。

    思考DIY迷你客户端开发手记(一)中的5中问题才是清除掉乱七八糟的工程之后的价值了。

  1.业务策略编程

       在整个应用中最核心的问题是:通过选择收件人的邮件地址的源文件,加载到收件人的集合中,进而发送相应的邮件。

      处理这个问题自然想到了策略模式。

     先定义一个接口,声明了子类需要实现的方法,然后通过不同的需求来实现其中的功能。

     编码-0:定义了解析文件中的联系人邮件地址的策略接口


  1. public interface AnalysisStrategy {  
  2.       
  3.     /**  
  4.      *   
  5.      * 解析联系人数据源  
  6.      *   
  7.      * @return list  
  8.      */ 
  9.     public List<String> analysisSrc();  
  10.       

     编码-1:主要的两种模式是,解析Excel文件和XML文件


  1. public class ExcelContacts implements AnalysisStrategy {  
  2.  
  3.     private File excelFile;  
  4.  
  5.     
  6.     public ExcelContacts(File f) {  
  7.         this.excelFile = f;  
  8.     }  
  9.  
  10.     /**  
  11.      * 联系人Excel表  
  12.      *  
  13.      * @help 参见规定的Excel格式  
  14.      *  
  15.      * @return list  
  16.      */ 
  17.     @Override 
  18.     public List<String> analysisSrc() {  
  19.         Workbook wb = null;  
  20.         List<String> contactsList = null;  
  21.         try {  
  22.             wb = Workbook.getWorkbook(excelFile);  
  23.             Sheet[] sheets = wb.getSheets();  
  24.             contactsList = new ArrayList<String>();  
  25.             for (int i = 0, j = sheets.length; i < j; i++) {  
  26.                 Cell[] cells = sheets[i].getColumn(2);  
  27.                 for (int row = 1, rows = cells.length; row < rows; row++) {  
  28.                     String str=cells[row].getContents().trim();  
  29.                     if(MiniMailTool.checkEmail(str)){  
  30.                         contactsList.add(str);  
  31.                     }  
  32.                 }  
  33.             }  
  34.         } catch (IOException ex) {  
  35.             Logger.getLogger(ExcelContacts.class.getName()).log(Level.SEVERE, null, ex);  
  36.         } catch (BiffException ex) {  
  37.             Logger.getLogger(ExcelContacts.class.getName()).log(Level.SEVERE, null, ex);  
  38.         }  
  39.         return contactsList;  
  40.     }  
  41. }  
  42. //-----------------------------------------------------//  
  43.  
  44. public class XMLContacts implements AnalysisStrategy {  
  45.  
  46.     private File xmlFile;  
  47.  
  48.     public XMLContacts(File f) {  
  49.         this.xmlFile=f;  
  50.     }  
  51.  
  52.     /**  
  53.      * 联系人XML表   
  54.      *   
  55.      * @help 参见规定的XML格式  
  56.      *  
  57.      * @param xmlFile  
  58.      * @return list  
  59.      */ 
  60.     @Override 
  61.     public List<String> analysisSrc() {  
  62.         List<String> contactsList=null;  
  63.         try {  
  64.             SAXBuilder sb =new SAXBuilder();  
  65.             Document doc=sb.build(xmlFile);  
  66.             Element root=doc.getRootElement();  
  67.             List<Element> userList=root.getChildren("user");  
  68.             contactsList=new ArrayList<String>();  
  69.             for(int i=0, j=userList.size(); i<j; i++){  
  70.                 Element children=userList.get(i);  
  71.                 String str=children.getChildText("email").trim();  
  72.                 if(MiniMailTool.checkEmail(str)){  
  73.                     contactsList.add(str);  
  74.                 }  
  75.             }  
  76.         } catch (JDOMException ex) {  
  77.             Logger.getLogger(XMLContacts.class.getName()).log(Level.SEVERE, null, ex);  
  78.         } catch (IOException ex) {  
  79.             Logger.getLogger(XMLContacts.class.getName()).log(Level.SEVERE, null, ex);  
  80.         }  
  81.         return contactsList;  
  82.     }  

    通过这样的方式就可以将不同的文件的解析联系人的过程封装掉,对于调用者来讲是相同的,只需要面向接口编程就可以了。

   这里给出源文件的格式:

   EXCEL表的格式

DIY迷你邮件客户端开发手记(二) 

   XML格式:

DIY迷你邮件客户端开发手记(二)

     这里的格式可以按照已经约定的方式书写,当然亦可以自定义格式,这样就应该编写实现

AnalysisStrategy(联系人解析)接口。

2.处理一些关于字符串,邮件地址验证,获取收件人地址信息

       这样的问题一般在编程开始的时候会有所考虑,倒是带来的后续问题不大,如何有效的编写更加通用的代码,才是问题的关键。

       这里有个关于工具类的命名问题,比如:Utils,Tools,Helper等类的命名都是非常不可取的方式,命名要简明思议,并且能够传单一定的信息,像这个工具类处理哪方面的问题,都应该能够很好的放映出来。

       工具类有可能涉及到:字符串处理方面;文件解析,文件过滤方面;图形用户界面编程中的组件信息处理方面;特定的多出使用的方法,变量等;类的构造和管理等方面。

       这个应用程序设计的相关方法不是很多,较好的处理掉了。

      编码-2:邮件客户端程序的工具类 


  1. /**  
  2.  *  
  3.  * 邮件客户端程序工具类  
  4.  *  
  5.  * @author aiilive   
  6.  */ 
  7. public final class MiniMailTool {  
  8.  
  9.     /**  
  10.      * 获取框架在Windows中显示的中心点  
  11.      *  
  12.      * @param jf  
  13.      * @return 中心点  
  14.      */ 
  15.     public static Point getCenter(JFrame jf) {  
  16.         Point p = new Point();  
  17.         Dimension dim = jf.getSize();  
  18.         int width = dim.width;  
  19.         int height = dim.height;  
  20.         Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();  
  21.         p.setLocation((screenSize.width - width) / 2, ((screenSize.height - height) / 2));  
  22.         return p;  
  23.     }  
  24.  
  25.     /**  
  26.      * 通过收件人信息获取收件人  
  27.      *  
  28.      * @param contactsString  
  29.      * @return List  
  30.      */ 
  31.     public static List getToContacts(String contactsText) {  
  32.        String[] contacts = contactsText.split(";");   
  33.         return Arrays.asList(contacts);  
  34.     }  
  35.  
  36.     /**  
  37.      * 验证输入的联系人的电子邮箱的有效性  
  38.      *   
  39.      * @param contactsText  
  40.      * @return bo  
  41.      */ 
  42.     public static boolean checkContacts(String contactsText){  
  43.         String[] contacts = contactsText.split(";");  
  44.         boolean bo=true;  
  45.         for (int i = 0; i < contacts.length; i++) {  
  46.             contacts[i] = contacts[i].trim();  
  47.             if(!checkEmail(contacts[i])){  
  48.                 bo=false;  
  49.                 break;  
  50.             }  
  51.         }  
  52.         return bo;  
  53.     }  
  54.       
  55.     /**  
  56.      * 中文字符转换  
  57.      *  
  58.      * @param str  
  59.      * @return strEncode  
  60.      */ 
  61.     public static String chineseEncode(String str) {  
  62.         String strEncode = str;  
  63.         try {  
  64.             byte[] bts = str.getBytes("ISO-8859-1");  
  65.             strEncode = new String(bts, "GB2312");  
  66.         } catch (UnsupportedEncodingException ex) {  
  67.             Logger.getLogger(MiniMailTool.class.getName()).log(Level.SEVERE, null, ex);  
  68.         }  
  69.         return strEncode;  
  70.     }  
  71.  
  72.     /**  
  73.      * 将字符数组char [] 转化为字符串String  
  74.      *  
  75.      * @param ch []  
  76.      * @return String  
  77.      */ 
  78.     public static String arrayToString(char[] ch) {  
  79.         if (ch == null) {  
  80.             return "null";  
  81.         }  
  82.         StringBuilder b = new StringBuilder();  
  83.         for (int i = 0; i < ch.length; i++) {  
  84.             b.append(ch[i]);  
  85.         }  
  86.         return b.toString();  
  87.     }  
  88.  
  89.     /**  
  90.      * 验证电子邮件地址是否有效  
  91.      *  
  92.      * @param email 电子邮件地址字符串  
  93.      * @return 布尔值  
  94.      */ 
  95.     public static boolean checkEmail(String email) {  
  96.         Pattern pattern=Pattern.compile("\\w+@(\\w+.)+[a-z]{2,3}");  
  97.         Matcher matcher=pattern.matcher(email);  
  98.         return matcher.matches();  
  99.     }  

      上面的代码涉及到了用户界面组件的工具类方法,字符串处理,常用的验证等。对于一个较大的工程,或者是涉及相关的操作非常多和复杂的时候,就得考虑方法的组织,重构,提取,建立更好的类的层次关系这样才符合面向对象编程基本思想,才能够获得可以水平和垂直扩展的机会。同时使得代码的耦合度降到最低,想要达到如此美好的境况,又得回到设计和组织方面去。

3.用户界面的布局,各个组件在特定时间的状态

    正因为有用户界面,所以考虑各组件之间的组织关系,程序运行是组件的状态。活动图虽然集中注意力的面向的是活动参与者,对于桌面应用程序而言,每一个组件正可以看作是活动的参与者,因此正确对待组件状态,就可以呈现一个真实的活动状态。

    比如:在没有进行邮件信息检查时,发送按钮是禁用的;为发送邮件时,状态信息显示填写发件信息,发送完成时发送完成或者发送失败;验证收件人的电子邮件信息时;不符合格式的地址,显示相应的提示信息等等,这样都源于我们对客观的事物和感知,也是对我们的用户交互,人性化设计的要求。



本文转自 secondriver 51CTO博客,原文链接:http://blog.51cto.com/aiilive/1063926,如需转载请自行联系原作者

上一篇:利用ASP.NET MVC源代码调试你的应用程序


下一篇:DataWorks百问百答57:如何排查独享数据集成资源组网络问题?