装饰者模式
装饰者模式是一种结构型设计模式,它允许向现有对象添加新功能,同时又不改变其结构。装饰者模式通过创建一个包装对象来包裹真实对象,然后在包装对象中添加新的行为或功能。
以下是一个装饰者模式的案例:
假设有一个咖啡店,它提供不同种类的咖啡。我们希望能够为咖啡添加额外的配料,如牛奶、糖和巧克力等。而且,我们还希望能够动态地为咖啡添加或移除配料。
首先,我们定义一个咖啡接口,它有一个获取价格的方法:
public interface Coffee {
double getPrice();
}
然后,我们创建一个具体的咖啡类,实现咖啡接口:
public class SimpleCoffee implements Coffee {
@Override
public double getPrice() {
return 2.0;
}
}
接下来,我们创建一个装饰者抽象类,它也实现咖啡接口,并包含一个咖啡对象作为成员变量:
public abstract class CoffeeDecorator implements Coffee {
protected Coffee coffee;
public CoffeeDecorator(Coffee coffee) {
this.coffee = coffee;
}
@Override
public double getPrice() {
return coffee.getPrice();
}
}
然后,我们创建具体的装饰者类,它继承自装饰者抽象类,并在其中添加额外的功能:
public class MilkDecorator extends CoffeeDecorator {
public MilkDecorator(Coffee coffee) {
super(coffee);
}
@Override
public double getPrice() {
return super.getPrice() + 0.5;
}
}
public class SugarDecorator extends CoffeeDecorator {
public SugarDecorator(Coffee coffee) {
super(coffee);
}
@Override
public double getPrice() {
return super.getPrice() + 0.3;
}
}
public class ChocolateDecorator extends CoffeeDecorator {
public ChocolateDecorator(Coffee coffee) {
super(coffee);
}
@Override
public double getPrice() {
return super.getPrice() + 0.8;
}
}
最后,我们可以使用装饰者模式来创建不同种类的咖啡,并动态地为其添加配料:
public class Main {
public static void main(String[] args) {
Coffee coffee = new SimpleCoffee();
coffee = new MilkDecorator(coffee);
coffee = new SugarDecorator(coffee);
coffee = new ChocolateDecorator(coffee);
System.out.println("Coffee price: " + coffee.getPrice());
}
}
输出结果为:
Coffee price: 3.6
通过装饰者模式,我们可以动态地为咖啡添加不同的配料,而不需要修改咖啡类的代码。这样就实现了对现有对象的功能扩展,同时又保持了代码的灵活性和可维护性。
代理模式和装饰者模式的差异
代理模式和装饰者模式都是结构型设计模式,它们都可以在不改变原有对象的情况下,对对象进行功能扩展。
然而,代理模式和装饰者模式有以下几点差异:
- 目的不同:代理模式的主要目的是控制对真实对象的访问,可以在访问真实对象前后执行一些额外的操作,例如权限控制、缓存、日志记录等。装饰者模式的主要目的是为对象动态添加新的行为或功能,可以在不改变原有对象的结构的情况下,对对象进行功能扩展。
- 关注点不同:代理模式关注于控制对真实对象的访问,代理对象通常会持有一个真实对象的引用,并在访问真实对象前后执行一些额外的操作。装饰者模式关注于为对象添加新的行为或功能,装饰者对象通常会持有一个被装饰对象的引用,并在调用被装饰对象的方法前后执行一些额外的操作。
- 对象关系不同:在代理模式中,代理对象和真实对象实现相同的接口,客户端通常通过代理对象来访问真实对象。在装饰者模式中,装饰者对象和被装饰对象实现相同的接口,客户端可以通过装饰者对象来动态地为被装饰对象添加新的行为或功能。
- 生命周期不同:代理对象通常具有和真实对象相同的生命周期,它们的创建和销毁通常是一起的。装饰者对象可以在运行时动态地被添加或移除,它们的生命周期可以和被装饰对象不一致。
总的来说,代理模式主要用于控制对真实对象的访问,并在访问前后执行一些额外的操作;装饰者模式主要用于为对象动态添加新的行为或功能。选择使用哪种模式取决于具体的需求和设计目标。