1、java的功能增强
讲装饰器模式之前,我们先来思考一个问题,如何对java对象进行功能增强?
绝大多数人在初学java时面对这个问题时,第一时间想到的便是继承,子类通过继承父类,在父类的基础上增加一些自己的功能,就可以完成最简单的增强。
实际上java用来做功能增强的方式有三种:
1.继承
2.装饰器模式
3.代理模式
本章节就为何要使用装饰器模式进行讲解。
2、继承
这确实是一种增强的模式,我们先来看看代码怎么写:
回到之前我们举的经典例子,有一个被叫做Liunan的程序员 ,实现了一个叫做Coding的方法
public class Liunan{
public void coding()
{
System.out.println("writing.");
}
}
此时Liunan收了一个徒弟,他的徒弟除了要自己写代码以外,还要组织代码review,那么我们可以实现一个子类,来完成功能的增强
public class SubLiunanForReview extends Liunan
{
public void organize()
{
System.out.println("review code.");
}
}
这时Liunan又收了一个徒弟,需要负责review, commit, publish,那么我们可以让这个徒弟完成SubLiunanForReview 的继承,并在其基础上增加commit 和 pulish 方法即可
public class SubLiunanForCommitAndPublish extends SubLiunanForReview
{
public void commit()
{
System.out.println("commit.");
}
public void publish()
{
System.out.println("publish.");
}
}
但是如果Liunan再次收徒(Liunan的徒弟好多),此时需要完成的任务又发生了变化,比如我们只要求可以进行commit 和 review,不需要完成publish,按照继承的思路,我们又需要创建新的子类完成功能的增强。
因此在继承时我们不能完成:
- 子类只能增强指定的功能,并且无法动态发生变化;
- 如果父类是带有数据、信息、属性的话,那么子类无法增强。
3、装饰器模式
先不用纠结这个名词,回到刚才的问题,Liunan有三个徒弟,分别需要实现coding、review、commit、publish四种功能,若使用继承来实现,那么我们将出现类爆炸的模式,因此我们可以换一种思路,既然这四类功能都是组合的关系,且都需要实现coding方法(因为我们是程序员啦~)
那我们先创建一个接口
public interface IProgramer
{
void coding();
}
然后以Liunan作为基本的IProgramer实现类
public class Liunan implements IProgramer
{
public void coding()
{
System.out.println("liunan is writing.");
}
}
此时我们创建一个“包装”,这个包装是一个抽象类,它实现了IProgramer接口,并完成了对基础类Programer的包装
public abstract class ProgramerDecorator implements IProgramer
{
private IProgramer programer;
public ProgramerDecorator(IProgramer programer)
{
this.programer = programer;
}
@Override
public void coding()
{
programer.coding();
}
}
然后根据ProgramerDecorator提供基础的功能扩展,分别是review:
public class ProgramerReview extends ProgramerDecorator
{
public void review()
{
System.out.println("review.");
}
@Override
public void coding()
{
super.coding();
review(); //对coding进行增强
}
public ProgramerReview(IProgramer programer)
{
super(programer);
}
}
Commit:
public class ProgramCommit extends ProgramerDecorator
{
public void commit()
{
System.out.println("commit");
}
@Override
public void coding()
{
super.coding();
commit();
}
public ProgramCommit(IProgramer programer)
{
super(programer);
}
}
Publish:
public class ProgramPublish extends ProgramerDecorator
{
public void publish()
{
System.out.println("publish.");
}
@Override
public void coding()
{
super.publish();
review();
}
public ProgramPublish(IProgramer programer)
{
super(programer);
}
}
然后我们来思考,我们要实现
public static void decorator()
{
System.out.println("----only write.");//程序员只写代码
IProgramer programer = new Liunan();
programer.coding();
System.out.println("----write and commit.");//程序员写完代码之后提交
IProgramer programer1 = new ProgramCommit(new Liunan());
programer1.coding();
System.out.println("----write and commit and pubish review.");//程序员写完代码后提交,发布,再review。
IProgramer programer2 = new ProgramerReview(new ProgramPublish(new ProgramCommit(new Liunan())));
programer2.coding();
}
执行结果:

此时如果想进行任务的顺序调整,我们只需要修改Program的创建顺序,就能完成,而不需要再进行代码的编写。 代码如下:
public static void decorator()
{
System.out.println("----only write.");
IProgramer programer = new Liunan();
programer.coding();
System.out.println("----write and commit.");
IProgramer programer1 = new ProgramCommit(new Liunan());
programer1.coding();
System.out.println("----write and commit and pubish review.");
IProgramer programer2 = new ProgramerReview(new ProgramPublish(new ProgramCommit(new Liunan())));
programer2.coding();
System.out.println("----write and review and commit publish.");
IProgramer programer3 = new ProgramPublish(new ProgramCommit(new ProgramerReview(new Liunan())));
programer3.coding();
}
执行结果:

总结 以上,我们对装饰器模式做一个总结:
-
装饰器与基本功能类需要实现同一个接口;
-
装饰器可对所有实现了此接口的类进行增强,包含它自己;
-
不同的功能可以抽象成独立的装饰器,在装饰器中对需要增强的方法进行功能增强,如本题中,ProgramPublish装饰器增强的对象为Liunan,增强的功能为publish,我们可进一步对ProgramPublish继续进行增强。我们包装完还是IProgram类型,无论包装多少层,返回的对象都是is-a的关系;
4、代理模式
待补充。
原创文章,转载请注明出处,多谢。