什么是装饰者模式:
在java中,如果你希望扩展现有类的功能,那么你一定首先想到的是继承现有类(至少我是这样),那么装饰者模式可以让你不使用继承,一样扩展现有类的功能,且不需要对现有类进行修改,让你多了一种扩展现有类的功能的选择。
设计原则
对扩展开发,对修改关闭。
java.io包内的大量的类都是装饰者,下面这张图就一目了然了
这张图来自http://prowl.iteye.com/blog/477100我为了图个方便就不去自己画了,对原作者表示感谢。
它的原始出处应该是来自Head First Design Pattern P101。今天的这个例子也是摘自这本书中的,不过我对其进行了一些改动,以便适合在Android上运行。
要实现的东西是:在assets文件夹中放入一个写有字符的txt文本文件,我将它读取出来,然后通过使用自定义的装饰者类将它里面的所有的大写字符改为小写。
效果图:
下面直接上代码:
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<!-- 原始字符 -->
<TextView
android:id="@+id/tv_originality_character"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
/>
<!-- 转换后的小写字符 -->
<TextView
android:id="@+id/tv_lower_character"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/tv_originality_character"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
/>
</RelativeLayout>
MainActivity.java
public class MainActivity extends Activity {
private TextView tvShowOriginalityCharacter;
private TextView tvShowLowerCharacter;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvShowOriginalityCharacter = (TextView)findViewById(R.id.tv_originality_character);
tvShowLowerCharacter = (TextView)findViewById(R.id.tv_lower_character);
//显示data.txt中原来的文字
try {
InputStream is = getAssets().open("data.txt");
String str = "";
int c;
while((c = is.read()) >= 0)
{
str = str + (char)c;
}
tvShowOriginalityCharacter.setText(str);
} catch (IOException e) {
e.printStackTrace();
}
//显示data.txt中转为小写字符后的文字
try {
LowerCaseInputStream lcis = new LowerCaseInputStream(getAssets().open("data.txt"));
String str = "";
int c;
while((c = lcis.read()) >= 0)
{
str = str + (char)c;
}
tvShowLowerCharacter.setText(str);
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 注意这个类的构造器接收的参数是InputStream类型。
* 覆盖read()方法,这实际上和你写一个类extend InputStream,然后Override它的read()方法所达到的效果是一样的。
* 当然,你不仅可以覆盖这个类原来的方法,也可以让这个类添加新的方法。这也和继承起到的作用是一样的。
*
* LowerCaseInputStream就是一个装饰者。
*
* */
class LowerCaseInputStream extends FilterInputStream
{
public LowerCaseInputStream(InputStream in)
{
super(in);
}
@Override
public int read() throws IOException
{
int c = super.read();
return (c == -1 ? c : Character.toLowerCase((char)c));
}
//You can add some more methods...
}