装饰者模式动态地将责任附加到对象身上。若要拓展功能,装饰者提供了比继承更有弹性的替代方案。
用过 QQ
的人都知道, 它有很多特权服务,比如说 Vip
, SVip
等。我们就以此为例对装饰者模式进行讲解。
public class User {
private String des;
public User() {
des = "I am common user";
}
public String getDes() {
return des;
}
public void function() {
System.out.println("I can use common function.");
}
}
可见,在这里我们只是一个普通用户,而且也只能使用普通用户的功能。那么接下来,我们想要将普通用户升级为会员,可以使用会员功能,怎么办呢?难道这个时候我们还要去修改 function()
中的代码吗?如果真是这样,工作量真是大的难以想象。而且出于让我们得代码遵守开闭原则的目的,我们不能去盲目的修改源代码。下面我们就用装饰者模式将普通用户升级为 Vip
用户。
首先,我们需要保证装饰者和被装饰对象有相同的超类型,所以我们现在将用户写成一个抽象类。
public abstract class User {
public User() {
}
public String getDes() {
return "I am common user";
}
public abstract void function();
}
下面开始书写装饰对象,装饰者可以在被装饰者行为之前或者之后或者覆盖原功能加上自己的行为,以达到特定的目的。下面我们也为装饰者对象写一个抽象类,并让其继承自 User
用以保证装饰者和被装饰者拥有共同的父类。
public abstract class Decorator extends User {
public abstract String updateTime();
}
update()
方法用以记录装饰者添加到被装饰者上的时间。下面我们就去写一个 Vip
装饰者,试一下功能。
public class VipDecorator extends Decorator {
private Date mDate;
private User user;
public VipDecorator(User user) {
mDate = new Date();
this.user = user;
}
@Override
public String updateTime() {
return mDate.toString();
}
@Override
public void function() {
user.function();
System.out.println("Vip function. ");
}
@Override
public String getDes() {
return "I am vip user.";
}
}
其实,我们应该在Decorator
抽象类里将 getDes()
和 function()
方法继续声明为抽象方法,强制子类实现这两个方法,否则很可能会遗漏。比如我一开始就漏写了 getDes()
方法。
public class Client {
public static void main(String[] args) {
User user = new CommonUser();
System.out.println(user.getDes());
user.function();
System.out.println("-------------------------");
user = new VipDecorator(user);
System.out.println(user.getDes());
user.function();
}
}
输出结果为
I am common user
Common function.
-------------------------
I am vip user.
Common function.
Vip function.
可见,这个时候我们想要的功能就实现了。而且,如果以后我们想增加其它的功能也不需要修改源代码。比如说,现在我想添加 SVip
.
public class SVipDecorator extends Decorator {
private Date mDate;
private User user;
public SVipDecorator(User user) {
mDate = new Date();
this.user = user;
}
@Override
public String updateTime() {
return mDate.toString();
}
@Override
public void function() {
user.function();
System.out.println("SVip function. ");
}
@Override
public String getDes() {
return "I am SVip user";
}
}
在原来的基础上进项测试。
public class Client {
public static void main(String[] args) {
User user = new CommonUser();
System.out.println(user.getDes());
user.function();
System.out.println("-------------------------");
user = new VipDecorator(user);
System.out.println(user.getDes());
user.function();
System.out.println("-------------------------");
user = new SVipDecorator(user);
System.out.println(user.getDes());
user.function();
}
}
打印结果为
I am common user
Common function.
-------------------------
I am vip user.
Common function.
Vip function.
-------------------------
I am SVip user
Common function.
Vip function.
SVip function.