重构了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).
总的来说还是挺好用的,而且也不难,最关键的是
优雅!
用了设计模式之后我整个人都升华了你知道吗