装饰器模式:在不必改变原类文件和使用继承的情况下,动态的扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。
装饰器模式的使用过程:
1.创建一个接口,然后写方法
2.创建类实现该接口,并实现接口里的方法
3.创建包装类,也实现上面的接口和方法
4.在包装类中声明被包装类的类型,通过构造器的方式注入
5.在包装类中,不需要修改的方法,直接调用被包装类的方法即可,只需要修改的自己关注的方法。
代码示例
1.创建接口Ups,并声明了3个方法
public interface Ups {
void start();
void stop();
void work();
}
2.写实现类SimpleUps
/**
* 普通ups
*/
public class SimpleUps implements Ups{
@Override
public void start() {
System.out.println("开始启动..");
}
@Override
public void stop() {
System.out.println("停止工作..");
}
@Override
public void work() {
System.out.println("工作中..");
}
}
3.创建包装类,对SimpleUps的start方法进行增强,为了代码的可扩展性,我们传入的是SimpleUps对应的接口,而不是具体的实现类
/**
* 高级ups
*/
public class SinorUps implements Ups{
private Ups ups;
public SinorUps(Ups ups) {
this.ups = ups;
}
@Override
public void start() {
System.out.println("开始启动前检查一下..");
this.ups.start();
}
@Override
public void stop() {
System.out.println("停止工作..");
}
@Override
public void work() {
System.out.println("工作中..");
}
}
4.代码测试和结果输出
public class TestUps {
public static void main(String[] args) {
Ups ups = new SinorUps(new SimpleUps());
ups.start();
}
}
可以看出在被包装类的基础上多输出了我们自己增加的。
对上面的代码,我们可以做一下改动,加一层抽象类AbstractUps,
public abstract class AbstractUps implements Ups{
private Ups ups;
public AbstractUps(Ups ups) {
this.ups = ups;
}
@Override
public void start() {
this.ups.start();
}
@Override
public void stop() {
this.ups.stop();
}
@Override
public void work() {
this.ups.work();
}
}
修改SinorUps类,只增强我们需要关注的方法
/**
* 高级ups
*/
public class SinorUps extends AbstractUps{
public SinorUps(Ups ups) {
super(ups);
}
@Override
public void start() {
System.out.println("开始启动前检查一下..");
super.start();
}
}
输出测试
public class TestUps {
public static void main(String[] args) {
Ups ups = new SinorUps(new SimpleUps());
ups.start();
System.out.println("=============================");
ups.work();
}
}
从上面可以看出,装饰类并没有对原始类做任何修改和破坏,也没有继承原始类。如果还有类实现类Ups接口,需要对start方法做同样的增强,则只需要在Ups ups = new SinorUps(new SimpleUps());传入需要增强的实例对象即可。例如创建SimpleUpsV2实现Ups接口
**
* v2版本ups
*/
public class SimpleUpsV2 implements Ups{
@Override
public void start() {
System.out.println("v2版本开始启动..");
}
@Override
public void stop() {
System.out.println("v2版本停止工作..");
}
@Override
public void work() {
System.out.println("v2版本工作中..");
}
}
对start方法做同样的增强
public class TestUps {
public static void main(String[] args) {
System.out.println("================V2版本=============");
Ups upsV2 = new SinorUps(new SimpleUpsV2());
upsV2.start();
}
}
上述方法如果用继承的方式实现,则需要分别创建Simple和SimpleV2的子类,若Ups的接口的子类非常多的话,且都需要对某一方法做同样的增强,用继承的方式去实现,就需要创建非常多的子类,代码会很庞大。
继承与装饰器总结
1.装饰器模式比继承要灵活。避免了继承体系臃肿
2.装饰器模式降低了类于类之间的关系。
3.用装饰器实现的功能,继承能否实现,是可以的,但是在代码的结构层次上来说,装饰器模式比继承灵活了很多。
4.装饰模式与继承关系的目的都是要拓展对象的功能,但是装饰模式可以提供比继承更多的灵活性。装饰模式允许系统动态决定“贴上”一个需要的“装饰”,或者“除掉”一个不需要的“装饰”。继承关系则不同,继承关系是静态的,它在系统运行前就决定了