java装饰者模式

来源:互联网 发布:网站seo分析报告 编辑:程序博客网 时间:2024/06/04 20:01

装饰者模式定义:动态地将责任附加到对象上,若要扩展功能,装饰者提供了比继承更有弹性的替代方案;

 

设计原则:

类应该对扩展开放,对修改关闭;(目的是:让类容易扩展,在不修改现有代码的情况下,搭配新的行为);

 

举个例子:

地球村住着:学生,医生,警察等类型的人;

现在有:鸭子冒,牛仔裤,外套,内衣,鞋子等;

现在怎么设计这个类:让人穿上这些‘装饰’,就是说每一个人物对象都有衣服的修饰,可以穿两件内衣,一个帽子,一双鞋子;怎么实现人的display()能够恰当的显示出他的所有的装备呢?同时每件装备都有价格,怎么实现总的cost()呢?而且不断会有新款的装备,那么要怎么让新款的装备很好的嵌入到总设计中呢?

利用装饰者模式,有如下的设计:

代码如下所示:

abstract class Person{String description = "None";public String getDisplay(){return description;}public abstract int cost();}class Doctor extends Person{public Doctor(){description = "a Doctor";}@Overridepublic int cost() {// TODO Auto-generated method stubreturn 0;}}class Student extends Person{public Student(){description = "a Student";}@Overridepublic int cost() {// TODO Auto-generated method stubreturn 0;}}abstract class Equipments extends Person{public abstract String getDisplay();}class Shoes extends Equipments{Person person;public Shoes(Person person){this.person = person; }@Overridepublic String getDisplay() {// TODO Auto-generated method stubreturn person.getDisplay()+",Shoes";}@Overridepublic int cost() {// TODO Auto-generated method stubreturn 5+person.cost();}}class Coat extends Equipments{Person person;public Coat(Person person){this.person = person; }@Overridepublic String getDisplay() {// TODO Auto-generated method stubreturn person.getDisplay()+",Coat";}@Overridepublic int cost() {// TODO Auto-generated method stubreturn 25+person.cost();}}

测试代码:

public class test {public static void main(String[] args) {// TODO Auto-generated method stubPerson  doc = new Doctor();Person stu = new Student(); stu = new Coat(stu);stu = new Coat(stu);stu = new Shoes(stu);doc = new Coat(doc);doc = new Shoes(doc);System.out.println(doc.getDisplay()+"花费:"+doc.cost());System.out.println(stu.getDisplay()+"花费:"+stu.cost());}}

代码能够执行的关键是:

1:无论是Student,Doctor或者Coat,Shoes都是直接或者间接的继承了类Person;

2:先有人物Person stu =  new Student(),然后stu = newCoat(stu);是将stu指向新的对象,而将stu隐藏在内部变量person中;画成图,大概是以下这种效果:

JDK中有一些使用该模式的设计,加深下理解吧;

下面是典型的对象集合,用装饰者来将功能结合起来,以读取文件数据:


 

装饰java.IO类

输入字节流:



为了分析方便,我们从源码中截取InputStream,FileinputStream,FilterInputSteam的对我们分析有帮助的一小部分代码;

InputStream抽象类:(相当于之前的Person类)public abstract class InputStream implements Closeable{  public abstract int read() throws IOException;}FileInputStream类(相当于之前的Doctor类)public class FileInputStream extends InputStream{  public FileInputStream(String name) throws FileNotFoundException {        this(name != null ? new File(name) : null);}public int read() throws IOException {        Object traceContext = IoTrace.fileReadBegin(path);        int b = 0;        try {            b = read0();        } finally {            IoTrace.fileReadEnd(traceContext, b == -1 ? 0 : 1);        }        return b;    }} FileInputStream类(相当于之前的Equipments类)Public class FilterInputStream extends InputStream {protected volatile InputStream in;protected FilterInputStream(InputStream in) {        this.in = in;    }public int read() throws IOException {        return in.read();    }}

显然,如果要我们来写一个LowerCaseInputStream的类,相信难度已经不会很难了;

class LowerCaseInputStream extends FilterInputStream{public LowerCaseInputStream(InputStream in){super(in);}public int read() throws IOException{int c = super.read();return (c==-1?c:Character.toLowerCase((char) c));}}

测试代码:

public class test1 {public static void main(String[] args) {// TODO Auto-generated method stubint c;InputStream in=null;try {in = new FileInputStream("D:\\xx.txt");in=new LowerCaseInputStream(in);while((c=in.read())>=0){System.out.print((char)c);} }catch (FileNotFoundException e1) {// TODO Auto-generated catch blocke1.printStackTrace();}catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}




0 0