专业的JAVA编程教程与资源

网站首页 > java教程 正文

Java设计模式之装饰模式(java装饰模式和代理模式)

temp10 2025-07-28 20:16:04 java教程 7 ℃ 0 评论

装饰模式

通常情况下,扩展一个类的功能会使用继承方式来实现。但继承具有静态特征,耦合度高,并且随着扩展功能的增多,子类会很膨胀。如果使用组合关系来创建一个包装对象(即装饰对象)来包裹真实对象,并在保持真实对象的类结构不变的前提下,为其提供额外的功能,这就是装饰模式的目标。

定义:指在不改变现有对象结构的情况下,动态地给该对象增加一些额外功能的模式,它属于对象结构型模式。装饰模式允许你将功能嵌套地堆叠在一起,以实现各种不同的功能组合,同时保持代码的灵活性和可维护性。

Java设计模式之装饰模式(java装饰模式和代理模式)

特点

优点:

  • 采用装饰模式扩展对象的功能比采用继承方式更加灵活。
  • 可以设计出多个不同的具体装饰类,创造出多个不同行为的组合。

缺点:

  • 装饰模式增加了许多子类,如果过度使用会使程序变得很复杂。

结构与实现

装饰模式的优点包括避免了类爆炸问题,因为你可以通过组合少量的装饰类来实现各种功能组合。它也使得功能的增加和修改更加灵活,不会影响到其他部分的代码。然而,装饰模式可能会导致增加很多小型的类,从而增加了代码的复杂性。

涉及以下角色:

  • 组件(Component):定义了一个抽象的接口,可以是具体对象或装饰器所共有的接口。如示例代码中的Coffee;
  • 具体组件(Concrete Component):实现了组件接口,是被装饰的原始对象。如示例代码中的BaseCoffee;
  • 装饰器(Decorator):持有一个指向组件对象的引用,并实现了组件的接口。它可以包含额外的功能,也可以将请求传递给组件对象。如示例代码中的CoffeeDecorator;
  • 具体装饰器(Concrete Decorator):扩展了装饰器类,通过添加额外的功能来装饰具体组件。如示例代码中的Americano、Lattecaffe。

类图结构如下:

代码如下:

Coffee.java

public interface Coffee {

	double cost();
	int sweetness();
	String desc();
	
}

BaseCoffee.java

public class BaseCoffee implements Coffee {

	@Override
	public double cost() {
		return 10d;
	}
	@Override
	public int sweetness() {
		return 0;
	}
	@Override
	public String desc() {
		return "基础咖啡";
	}

}

CoffeeDecorator.java

public abstract class CoffeeDecorator implements Coffee {

	protected Coffee coffee;
	
	public CoffeeDecorator(Coffee coffee) {
		this.coffee = coffee;
	}
	@Override
	public double cost() {
		return coffee.cost();
	}
	@Override
	public int sweetness() {
		return coffee.sweetness();
	}
	@Override
	public String desc() {
		return coffee.desc();
	}

}

Americano.java

public class Americano extends CoffeeDecorator {

	public Americano(Coffee coffee) {
		super(coffee);
	}
	@Override
	public double cost() {
		return coffee.cost() + 2D;
	}
	@Override
	public int sweetness() {
		return coffee.sweetness() + 5;
	}
	@Override
	public String desc() {
		return coffee.desc() + ",加冰";
	}

}

Lattecaffe.java

public class Lattecaffe extends CoffeeDecorator {

	public Lattecaffe(Coffee coffee) {
		super(coffee);
	}
	@Override
	public double cost() {
		return coffee.cost() + 5D;
	}
	@Override
	public int sweetness() {
		return coffee.sweetness() + 7;
	}
	@Override
	public String desc() {
		return coffee.desc() + ",加奶泡";
	}
}

DecoratorTest.java

public class DecoratorTest {
	public static void main(String[] args) {
		Coffee coffee = new BaseCoffee();
		CoffeeDecorator americano = new Americano(coffee);
		System.out.println(MessageFormat.format("美式咖啡价格{0}元,甜度{1},{2}。", 
				americano.cost(), americano.sweetness(), americano.desc()));
		CoffeeDecorator lattecaffe = new Lattecaffe(coffee);
		System.out.println(MessageFormat.format("卡布奇诺价格{0}元,甜度{1},{2}。", 
				lattecaffe.cost(), lattecaffe.sweetness(), lattecaffe.desc()));
	}
}

应用场景

通常在以下几种情况使用:

  • 当需要给一个现有类添加附加职责,而又不能采用生成子类的方法进行扩充时。例如,该类被隐藏或者该类是终极类或者采用继承方式会产生大量的子类;
  • 当需要通过对现有的一组基本功能进行排列组合而产生非常多的功能时,采用继承关系很难实现,而采用装饰模式却很好实现;
  • 当对象的功能要求可以动态地添加,也可以再动态地撤销时。

装饰模式在 Java语言中的最著名的应用莫过于 Java I/O 标准库的设计了。例如,InputStream 的子类 FilterInputStream,OutputStream 的子类 FilterOutputStream,Reader 的子类 BufferedReader 以及 FilterReader,还有 Writer 的子类 BufferedWriter、FilterWriter 以及 PrintWriter 等,它们都是抽象装饰类。

装饰模式所包含的 4 个角色不是任何时候都要存在的,在有些应用环境下模式是可以进行简化。

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表