java设计模式——装饰者模式浅析

前几天帮同学做试卷发现有个编程题居然让用Decorator来写,以前只接触过简单的设计模式,现在有时间准备好好认真学习一下设计模式。如果你只会code那么你永远都只是code,如果你会设计模式和算法那么你绝不单单只能做code。

 

装饰设计模式简单的说来就是为了动态的增加已有类的功能。有些人也许会说增加已有类的功能那么继承该类重写或者添加方法不就行了吗?但是这样只会让程序更加的臃肿,如果要增加的功能种类很多,势必要创建很多的子类,而且使用子类来增加父类的功能势必是静态的是已经预定义好的。故装饰设计模式诞生了,为了动态的增加原类的功能。

为了增加一个类的功能你是再生成一个他的子类来扩展的呢?还是写个类把这个对象直接传进去好呢?这个也许你认为不好回答。那如果你又不想要这些扩展的功能了,你要去掉这些功能,那么第一种去掉简单呢还是第二种的呢?这个答案肯定是第二种了,第二种去掉不影响以前的功能,灵活性相当强。

装饰模式主要有两部分组成被装饰的和装饰类。被装饰者就相当于基类,就是相当于那个功能不强的类,装饰类是为了增加那个功能不强的类而写的增强类。所以装饰类和被装饰类通常都是属于一个体系中的。

 

要点:装饰类与被装饰类属于同一个超类,继承的目的是为了继承类型不是为了扩展功能。继承类型可以让这种扩展串起来。即扩展1功能可以与扩展的2功能串行或串更多。下面举一个例子,代码若有错误,往海涵指正。

public abstract class Person {
    public String name;
    public abstract String getName();
    public abstract String doWork();
}
public class NewPerson extends Person {
    public NewPerson(String name){
    	super.name=name;
    }
	@Override
	public String getName() {
		// TODO Auto-generated method stub
		return super.name;
	}

	@Override
	public String doWork() {
		// TODO Auto-generated method stub
		return " 学习编码 ";
	}
}
public class OldPerson extends Person {
    public OldPerson(String name){
    	super.name=name;
    }
	@Override
	public String getName() {
		// TODO Auto-generated method stub
		return super.name;
	}

	@Override
	public String doWork() {
		// TODO Auto-generated method stub
		return " 设计软件 ";
	}
}
public abstract class CodeWork extends Person {
    public Person person;
    public CodeWork(Person per){
    	this.person=per;
    }
	@Override
	public String getName() {
		// TODO Auto-generated method stub
		return person.getName();
	}
	@Override
	public String doWork() {
		// TODO Auto-generated method stub
		return null;
	}

}
public class DoCode extends CodeWork {
	public DoCode(Person per){
    	super(per);
    }
	@Override
	public String doWork() {
		// TODO Auto-generated method stub
		return super.person.doWork()+coding();
	}
	public String coding(){
		return "编写代码";
	}
}
public class ChickCode extends CodeWork {
	public ChickCode(Person per){
    	super(per);
    }
	
	@Override
	public String doWork() {
		// TODO Auto-generated method stub
		return super.person.doWork()+chickCode();
	}
    public String chickCode(){
    	return " 检查代码 ";
    }
}
public class Test {

      public static void main(String[] args) {
		// TODO Auto-generated method stub
        Person newPerson=new NewPerson("王斌");
        System.out.println(newPerson.getName()+" 工作:"+newPerson.doWork());
        CodeWork code1=new DoCode(newPerson);
        System.out.println(code1.getName()+ " 工作:"+code1.doWork());
        CodeWork code2=new ChickCode(newPerson);
        System.out.println(code2.getName()+ " 工作:"+code2.doWork());
        CodeWork newRen=new ChickCode(code1);
        System.out.println(newRen.getName()+ " 工作:"+newRen.doWork());
        Person oldPerson=new OldPerson("老大");
        System.out.println(oldPerson.getName()+" 工作:"+oldPerson.doWork());
        code1.person=oldPerson;
        System.out.println(code1.getName()+ " 工作:"+code1.doWork());
	code2.person=oldPerson;
	System.out.println(code2.getName()+ " 工作:"+code2.doWork());
	newRen.person=code1;
	System.out.println(newRen.getName()+ " 工作:"+newRen.doWork());
     }

}
运行结果

王斌 工作: 学习编码 
王斌 工作: 学习编码 编写代码
王斌 工作: 学习编码  检查代码 
王斌 工作: 学习编码 编写代码 检查代码 
老大 工作: 设计软件 
老大 工作: 设计软件 编写代码
老大 工作: 设计软件  检查代码 
老大 工作: 设计软件 编写代码 检查代码 

其实也就是理解为刚开始新人(newperson)的工作只有学习代码,后来他的能力提升了,上司让他编写代码,之后又让他检查代码,之后整个代码工作都让他自己干了学习和写和检查。而那个老人(oldperson),本身就是大牛所以他的工作是设计软件。后来由于人手不够他不光要设计还有编写。有时候他需要设计但是让别人实施编写,自己只是检查这是第三种情况,最后有时候他接私活整个项目都自己干,设计编写和检查。

OldPerson和NewPerson这两个是被装饰者,DoCode和ChickCode是装饰者,他们增加了被装饰者的功能。装饰者和被装饰者也都继承了同一个超类Person,这样就使DoCode和ChickCode可以串行,降低了类的耦合度。摒弃了继承来扩展类功能的臃肿,其灵活性是非常大的。


之前见的考题:请编写程序实现数据文件“manager.txt”的读取,要求使用Decorator设计模式,通过自定义流来实现,文件格式如下

Ma2005001,Mike,1963.3
Ma2006003,tom,1972.11

public class ManagerReader extends FilterReader {//装饰者
    public ManagerReader(BufferedReader buffer){//BufferedReader为被装饰者
    	super(buffer);
    }
    public Manager readManager() throws IOException{
    	BufferedReader buffer=(BufferedReader)in;
    	String content=buffer.readLine();
    	if(content==null)return null;
    	String[] s=content.split(",");
    	Manager man=new Manager(s[0],s[1],s[2]);
    	return man;
    }
}
public class Manager {
   public String name;
   public String id;
   public String birth;
   public Manager(String s1,String s2,String s3){
	   this.name=s2;
	   this.id=s1;
	   this.birth=s3;
   }
   public String toString(){
	   return "学号:"+id+" 姓名:"+name+" 出生:"+birth;
   }
	public static void main(String args[]) throws IOException{//当然main可放在别的地方
	   File f = new File("c:/manager.txt");
	   FileReader in = new FileReader(f);
	   ManagerReader reader=new ManagerReader(new BufferedReader(in));
	   Manager man=reader.readManager();
	   while(man!=null){
		   System.out.println(man.toString());
		   man=reader.readManager();
	   }
   } 
}

结果:

学号:Ma2005001 姓名:Mike 出生:1963.3
学号:Ma2006003 姓名:tom 出生:1972.11


这个题很简单。只是没说清楚。说用装饰者模式自定义流。流可以对文件进行读取,逐字节或者逐字符但只是对文件的读取,装饰者扩展了流的功能,可以读取文件将每行数据转为对象。所以该写法符合装饰者模式,动态的扩展了类的功能。






  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值