重构了XmlDownloader类

用了建造者模式。

在公交车上考虑了两天,在脑子里大概画了个雏形,然后今晚解决了一些细节上的问题。

不废话,发代码:

  1 package com.mlxy.xml;

  2 

  3 import java.io.BufferedReader;

  4 import java.io.BufferedWriter;

  5 import java.io.File;

  6 import java.io.FileOutputStream;

  7 import java.io.InputStream;

  8 import java.io.InputStreamReader;

  9 import java.io.OutputStreamWriter;

 10 import java.net.MalformedURLException;

 11 import java.net.URL;

 12 

 13 import android.content.Context;

 14 import android.os.Environment;

 15 

 16 import com.mlxy.util.CharacterProcesser;

 17 

 18 /**

 19  * Xml文件下载器,重构完成。

 20  * 

 21  * @author mlxy

 22  * @version 1.1

 23  * */

 24 public class XmlDownloader {

 25     private Context parent;

 26     

 27     private String cityName = "南昌";

 28     private String city = CharacterProcesser.encodeByGB2312(cityName);

 29     private String password = "DJOYnieT8234jlsK";

 30     private int day = 0;

 31     private String link = "http://php.weather.sina.com.cn/xml.php?city=" + city

 32             + "&password=" + password + "&day=" + day;

 33     

 34     /** 私有构造方法,避免被外部实例化。*/

 35     private XmlDownloader() {

 36     }

 37     

 38     /** 根据给定的链接下载对应的xml文件。

 39      * 

 40      * @param link API的链接,需要标明网络协议。*/

 41     private void downloadXml(String link) {

 42         // 用链接字符串new出URL对象

 43         URL url = null;

 44         try {

 45             url = new URL(link);

 46         } catch (MalformedURLException e) {

 47             e.printStackTrace();

 48         }

 49 

 50         // 获取外部存储路径并创建文件对象。

 51         File externalDirectory = Environment.getExternalStorageDirectory();

 52         String fileName = "xml_resource.xml";

 53         File file = new File(externalDirectory, fileName);

 54 

 55         // 写文件。

 56         

 57         // 初始化io流。

 58         InputStream in = null;

 59         BufferedReader reader = null;

 60         FileOutputStream out = null;

 61         BufferedWriter writer = null;

 62         

 63         try {

 64             

 65             // 建立连接并给io流赋值。

 66             in = (InputStream) url.getContent();

 67             reader = new BufferedReader(new InputStreamReader(in, "iso-8859-1"));

 68             out = this.parent.openFileOutput(file.getName(), Context.MODE_PRIVATE);

 69             writer = new BufferedWriter(new OutputStreamWriter(out, "iso-8859-1"));

 70             

 71             // 读一行写一行,然后另起一行。

 72             String line = null;

 73             while ((line = reader.readLine()) != null) {

 74                 writer.write(line);

 75                 writer.newLine();

 76             }

 77             

 78         } catch (Exception e) {

 79             e.printStackTrace();

 80         } finally {

 81             try {

 82                 // 释放资源

 83                 writer.flush();

 84                 writer.close();

 85                 out.close();

 86                 reader.close();

 87                 in.close();

 88             } catch (Exception e2) {

 89                 e2.printStackTrace();

 90             }

 91         }

 92     }

 93     

 94     private void setParent(Context parent) {

 95         this.parent = parent;

 96     }

 97     

 98     private void setCity(String cityName) {

 99         this.cityName = cityName;

100     }

101     

102     private void setPassword(String password) {

103         this.password = password;

104     }

105     

106     private void setDay(int day) {

107         this.day = day;

108     }

109     

110     private String getLink() {

111         return this.link;

112     }

113     

114     public static class Builder {

115         /** 储存好的一个实例,留待建造完毕后返回。*/

116         private XmlDownloader instance = new XmlDownloader();

117         

118         /** 构造函数,需要输入启动此构造器的上下文视图作为参数。*/

119         public Builder(Context parent) {

120             instance.setParent(parent);

121         }

122         

123         /** 设置城市名。</br>

124          * 默认值为<b>南昌</b>。

125          * 

126          * @param cityName 城市名

127          * @return 构造器本身

128          */

129         public Builder setCity(String cityName) {

130             instance.setCity(cityName);

131             return this;

132         }

133         

134         /** 设置密码。</br>

135          * 默认值为<b>DJOYnieT8234jlsK</b>。

136          * 

137          * @param password API密码

138          * @return 构造器本身

139          */

140         public Builder setPassword(String password) {

141             instance.setPassword(password);

142             return this;

143         }

144         

145         /** 设置日期。</br>

146          * 默认值为<b>0</b>,也即是<b>今天</b>。</br>

147          * 以此类推。

148          * 

149          * @param day 日子,0为当天,范围在0-4

150          * @return 构造器本身

151          */

152         public Builder setDay(int day) {

153             instance.setDay(day);

154             return this;

155         }

156         

157         /** 用已经设置好的或默认的参数下载XML文件。*/

158         public void download() {

159             String link = instance.getLink();

160             instance.downloadXml(link);

161         }

162     }

163 }
需要结合前面几篇博文看

场景类则这么调用:

 构建Xml下载器并下载Xml文件。

new XmlDownloader.Builder(MainActivity.this)

        .setCity("南昌")

        .setPassword("DJOYnieT8234jlsK")

        .setDay(0)

        .download();

 

具体实现方式参考了安卓的Toast和Dialog等几个类。

 

纠结了一天要不要给建造者提供默认值,就是说在用户没有自己设定参数的情况下是直接返回null还是用默认值来处理。

白天一直想着,不能惯用户的毛病。

然后到了晚上,我一想,用户不就是我么,除了我谁还用我写的这个类,就果断用了默认值。

 

另外,因为XmlDownloader这个类是不需要实例的,所以:

  1. 把无参构造函数限制成了私有的,这样别人就没法访问构造函数,也就没法实例化它。

  2. 去掉了几乎所有getter方法,同时把所有方法和属性定为私有的,因为不会存在任何XmlDownloader对象,也就没有必要对外开放任何接口。

  2.3.3 求不提反射。

  3. 要记得给Builder类加上static关键字,因为我们需要通过外部类来直接访问它,如果忘了的话,就会出现这样的一个错误:

No enclosing instance of type XmlDownloader is accessible. Must qualify the allocation with an enclosing instance of type XmlDownloader (e.g. x.new A() where x is an instance of XmlDownloader).

 

总的来说还是挺好用的,而且也不难,最关键的是

优雅!

 

用了设计模式之后我整个人都升华了你知道吗

你可能感兴趣的:(download)