装饰器模式[Decorator]
:http://hi.baidu.com/fortin1001/blog/item/4a3c41e9d54bb23ab80e2d19.html
装饰器模式主要应用于这样一种场合,当你已经有了一个目标类,并且它是一个接口的实现类,在对该类使用的后期发现需要对相应接口程序的前后做更多的处理,这些处理是变化的,不固定的,但是有不能去修改这个目标类,这时我们就可以使用这个装饰器模式:
比如,我们已经有一个付款的方法 payMoney(long count) ,这个方法只负责将钱付给对方,不做其他操作,但是这时我们需要记录下这个付款的操作,并把这个操作记录到日志文件中以方便日后的查看,比如这个方法叫做 insertLog(String str) ,有一种办法就是使用继承,并复写相应的 payMoney(long count) 方法,这样也可以满足条件,但是问题出来了,如果我们又有其他的操作,例如通知付款人已经将款额付出 notic(String username) ,这时候这么办,当然我们仍然可以通过继承来实现,可是如果我现在有不想将付款操作记录到日志文件中了,那我又该这么办?
为了解决这种问题,我们使用了?装饰器模式?,在我们的应用中可以使用不同的装饰器类(以及装饰器类的组合)来达到以上的目的。
再将问题简化,我们要在控制台输出字符,但是需要在字符前后加上“*”和“+”,也就是说,我可能需要在我输入的字符前后加上“*”,也可能过了会儿又想加“+”而不是“*”,或者又想“*”和“+”都加上,有或者都不想加。
装饰器模式?让这些要求动态的配置出来,也就是说在运行时不需要改变原来已经生成好的对象。
让我们来看看这个解决方案的?装饰器模式?的类图吧:
?
其中,MyText 类为我们要显示的字符类,而 DecoratorTextConsole 及其子类为我们的?装饰类?。
具体代码如下:
/**********************************************************************/
package decorator.interfaces;
public interface TextConsole {
public void printWords();
public void readWords();
}
/**********************************************************************/
package decorator.service;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import decorator.interfaces.TextConsole;
public class MyText implements TextConsole {
private String words;
public void printWords() {
?? System.out.print(words);
}
public void readWords() {
?? BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
?? try{
??? System.out.print("please enter some word to display:");
??? words = br.readLine();
?? }catch(IOException e){
??? e.printStackTrace();
??? words = "There are some errors occured during your entering!";
?? }
}
}
/**********************************************************************/
package decorator.interfaces.impl;
import decorator.interfaces.TextConsole;
public class DecoratorTextConsole implements TextConsole {
private TextConsole text;
public DecoratorTextConsole(TextConsole text){
?? this.text = text;
}
public void printWords() {
?? text.printWords();
}
public void readWords() {
?? text.readWords();
}
}
/**********************************************************************/
package decorator.interfaces.impl;
import decorator.interfaces.TextConsole;
public class AsteriskTextConsole extends DecoratorTextConsole {
public AsteriskTextConsole(TextConsole text){
?? super(text);
}
public void printWords(){
?? addAsterisk();
?? super.printWords();
?? addAsterisk();
}
private void addAsterisk(){
?? System.out.print("*");
}
}
/**********************************************************************/
package decorator.interfaces.impl;
import decorator.interfaces.TextConsole;
public class PlusTextConsole extends DecoratorTextConsole {
public PlusTextConsole(TextConsole text){
?? super(text);
}
public void printWords(){
?? addPlus();
?? super.printWords();
?? addPlus();
}
private void addPlus(){
?? System.out.print("+");
}
}
/**********************************************************************/
package decorator;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import decorator.interfaces.TextConsole;
import decorator.interfaces.impl.AsteriskTextConsole;
import decorator.interfaces.impl.PlusTextConsole;
import decorator.service.MyText;
public class TestMain {
public static void main(String[] args){
?? TextConsole mt = new MyText();??? //?mt 实例在整个被调用的过程中都不会改变,但是它的其他装饰器类却是动态生成的,而且是可自由“拆卸”的,这样就比单一的继承灵活的多。
?? mt.readWords();
?? mt.printWords();
?? System.out.println();
??
?? String commond = new String();
?? System.out.println("please enter commond: (add ?(-plus | -astr | -all) | exit");
??
?? while(!commond.equals("exit")){
??? try{
???? commond = new BufferedReader(new InputStreamReader(System.in)).readLine();
??? }catch(IOException e){
???? e.printStackTrace();
???? commond = "exit";
??? }
??? if(commond.equals("add -plus")){
???? TextConsole ptc = new PlusTextConsole(mt);
???? ptc.printWords();
???? System.out.println();
??? }else if(commond.equals("add -astr")){
???? TextConsole atc = new AsteriskTextConsole(mt);
???? atc.printWords();
???? System.out.println();
??? }else if(commond.equals("add -all")){
???? TextConsole tc = new AsteriskTextConsole(new PlusTextConsole(mt));
???? tc.printWords();
???? System.out.println();
??? }else{
???? mt.printWords();
???? System.out.println();
??? }
?? }
}
}
/**********************************************************************/