Java设计模式之装饰模式

装饰器模式

在不改变原有类和继承关系的基础上,动态地拓展一个对象的功能。通过创建一个包装对象,包裹真实的对象,以完成功能的拓展。

想象一个场景,你有一辆车,它可以在陆地上跑,现在我需要一辆能在水里开的车。怎么办?继承汽车类,然后新增方法runInWater()?
好,可以。那么我现在需要一辆能飞的车。怎么办?继承汽车类,然后新增方法runInAir()?
好,可以。那么我现在需要一辆即能在水里开,又能在空中飞的车。怎么办?Java不支持多继承,难道又要去继承汽车类?还是去继承能在水里开的车,抑或是能飞的车?
然后功能继续增加,你就疯了。

在桥接模式的时候,已经疯过一次了,这里不能再疯了。

装饰模式和桥接模式的区别:

两个模式都是为了解决过多子类对象的问题,但是他们的诱因不同。
桥接模式是对象自身现有机制沿多个维度变化,是既有部分不稳定,装饰模式是为了增加新的功能。

下面开始上代码。本文示例,就是上述的多功能汽车。(本文示例参考自北京尚学堂Java教程,高淇)

先来一个汽车接口,只有一个方法move():

public interface ICar {
	void move();
}
再来一个ConcreteComponent具体构建对象,这就是真实对象:

//ConcreteComponent具体构件对象(真实对象)
class Car implements ICar{
	@Override
	public void move() {
		System.out.println("陆地上跑!");
	}
}
之后就是Decorator装饰对象:
//Decorator装饰角色
class SuperCar implements ICar{
	protected ICar car;
	
	public SuperCar(ICar car) {
		super();
		this.car = car;
	}

	@Override
	public void move() {
		car.move();
	}
}
装饰对象实现了ICar接口,并且持有一个ICar的引用,在重写的move()函数中,实际调用的传入的ICar引用的move()方法。

接着是具体的装饰角色:

//ConcreteDecorator具体装饰角色
class FlyCar extends SuperCar{

	public FlyCar(ICar car) {
		super(car);
	}
	
	public void fly(){
		System.out.println("天上飞");
	}
	
	@Override
	public void move() {
		super.move();
		fly();
	}
}
class WaterCar extends SuperCar{

	public WaterCar(ICar car) {
		super(car);
	}
	
	public void swim(){
		System.out.println("水里游");
	}
	
	@Override
	public void move() {
		super.move();
		swim();
	}
}
class AICar extends SuperCar{

	public AICar(ICar car) {
		super(car);
	}
	
	public void autoMove(){
		System.out.println("自动驾驶");
	}
	
	@Override
	public void move() {
		super.move();
		autoMove();
	}
}
最后测试一下:

public class Client {
	public static void main(String[] args) {
		Car car = new Car();
		car.move();
		
		System.out.println("==增加飞行功能==");
		
		FlyCar flyCar = new FlyCar(car);
		flyCar.move();
		
		System.out.println("==增加水上功能==");
		
		WaterCar waterCar = new WaterCar(car);
		waterCar.move();
		
		System.out.println("==全能车==");
		AICar aiCar = new AICar(new FlyCar(new WaterCar(car)));
		aiCar.move();
		
	}
}
首先我们有一个具体的真实对象Car,普通的车。开起来car.move();接着我们给他增加一个飞行功能,外面装饰一层FlyCar,开起来flyCar.move();再来一个全能车,装饰100层 生气

看下输出:

陆地上跑!
==增加飞行功能==
陆地上跑!
天上飞
==增加水上功能==
陆地上跑!
水里游
==全能车==
陆地上跑!
水里游
天上飞
自动驾驶
可以看到,随着装饰的层数增加,功能也增多了,但是没有增加多余的类。

总结:

装饰模式(Decorator)也叫包装器模式(Wrapper)
装饰模式降低系统耦合度,可以动态地增加或删除对象的职责,并使得需要装饰的具体构建类和具体装饰类可以独立变化,以便增加新的具体构建类和具体装饰类。
优点:
-拓展对象功能,比继承灵活,不会导致类个数急剧增加
-可以对一个对象进行多次装饰,创造出不同行为的组合,得到功能更加强大的对象
-具体构建类和具体装饰类可以独立变化,用户可以根据需要自己增加新的具体构建子类和具体装饰子类
确定:
-产生很多小对象。大量小对象占据内存,一定程度上影响性能。
-装饰模式易于出错,调试排查比较麻烦。

常用场景:

IO流实现细节就是典型的装饰模式
-Component抽象构件角色:
·io流中的InputStream、OutputStream、Reader、Writer
-ConcreteComponent具体构建角色
·io流中的FileInputStream、FileOutputStream
-Decorator装饰角色:
·持有一个抽象构件的引用:io流中的FilterInputStream、FilterOutputStream
-ConcreteDecorator具体装饰角色:
·负责给构建对象增加新的责任。io流中的BufferedOutputStream、BufferedInputStream等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值