装饰者模式
优化抽象类代码复用
- 定义抽象组件:首先定义一个抽象类(或接口)作为抽象组件,这是被装饰对象的基类。所有具体的组件(被装饰对象)和装饰器都继承(或实现)这个抽象组件。通过这种方式,抽象类的代码(如一些通用的方法)可以在具体组件中复用。
- 创建具体组件:继承抽象组件的具体类,它们是实际需要被装饰的对象,这些具体组件复用了抽象类的代码。
- 定义装饰器抽象类:同样继承抽象组件,装饰器抽象类持有一个抽象组件的引用,这样装饰器可以对任何实现了抽象组件的对象进行装饰。它提供了一个通用的装饰框架,复用了抽象组件的接口,使得具体的装饰器只需要关注额外功能的添加。
- 创建具体装饰器:继承装饰器抽象类,在具体装饰器中实现对具体组件的功能扩展,同时复用了装饰器抽象类和抽象组件的代码结构。
提高代码可维护性
- 单一职责:每个具体装饰器只负责添加一种特定的功能,遵循单一职责原则。如果某个功能需要修改,只需要修改对应的装饰器类,不会影响到其他装饰器和具体组件,降低了维护成本。
- 清晰的结构:装饰者模式通过组合的方式来扩展对象功能,结构清晰。新增或移除装饰器不会对原有组件的核心代码造成影响,使得代码维护更加直观。
提高代码可扩展性
- 灵活添加功能:当需要为现有组件添加新功能时,只需要创建一个新的具体装饰器类,继承装饰器抽象类并实现相应的功能扩展。不需要修改原有组件和其他装饰器的代码,大大提高了扩展性。
- 动态组合:可以在运行时根据需求动态地为对象添加或移除装饰器,这使得系统在面对不同场景时具有更高的灵活性和扩展性。
实际应用代码示例
// 抽象组件
abstract class Beverage {
String description = "Unknown Beverage";
public String getDescription() {
return description;
}
public abstract double cost();
}
// 具体组件
class Espresso extends Beverage {
public Espresso() {
description = "Espresso";
}
@Override
public double cost() {
return 1.99;
}
}
class HouseBlend extends Beverage {
public HouseBlend() {
description = "House Blend Coffee";
}
@Override
public double cost() {
return 0.89;
}
}
// 装饰器抽象类
abstract class CondimentDecorator extends Beverage {
protected Beverage beverage;
public CondimentDecorator(Beverage beverage) {
this.beverage = beverage;
}
}
// 具体装饰器
class Mocha extends CondimentDecorator {
public Mocha(Beverage beverage) {
super(beverage);
description = "Mocha";
}
@Override
public String getDescription() {
return beverage.getDescription() + ", Mocha";
}
@Override
public double cost() {
return 0.2 + beverage.cost();
}
}
class Whip extends CondimentDecorator {
public Whip(Beverage beverage) {
super(beverage);
description = "Whip";
}
@Override
public String getDescription() {
return beverage.getDescription() + ", Whip";
}
@Override
public double cost() {
return 0.1 + beverage.cost();
}
}
// 测试代码
public class CoffeeShop {
public static void main(String[] args) {
Beverage beverage = new Espresso();
System.out.println(beverage.getDescription() + " $" + beverage.cost());
Beverage beverage2 = new HouseBlend();
beverage2 = new Mocha(beverage2);
beverage2 = new Mocha(beverage2);
beverage2 = new Whip(beverage2);
System.out.println(beverage2.getDescription() + " $" + beverage2.cost());
}
}
策略模式
优化抽象类代码复用
- 定义抽象策略:创建一个抽象类(或接口)作为抽象策略,定义一系列相关算法的抽象方法。具体的策略类继承(或实现)这个抽象策略,通过这种方式复用抽象类中定义的算法框架。
- 创建具体策略:实现抽象策略中定义的方法,每个具体策略代表一种具体的算法实现,复用了抽象策略的定义。
- 定义上下文类:上下文类持有一个抽象策略的引用,通过组合的方式将具体策略注入到上下文类中。上下文类中可以定义一些通用的方法,利用抽象策略来实现不同的行为,这样也复用了抽象策略的代码结构。
提高代码可维护性
- 分离算法:每个具体策略类负责实现一种特定的算法,使得代码的职责更加清晰。如果某个算法需要修改,只需要修改对应的具体策略类,不会影响到其他策略和上下文类,降低了维护难度。
- 易于理解:策略模式将不同的算法封装在独立的类中,代码结构清晰,易于理解和维护。
提高代码可扩展性
- 新增算法:当需要添加新的算法时,只需要创建一个新的具体策略类,实现抽象策略的接口,然后在需要使用该算法的地方将新的策略注入到上下文类中。不需要修改原有策略和上下文类的核心代码,提高了扩展性。
- 动态切换:可以在运行时根据不同的条件动态地切换上下文类中使用的策略,使得系统能够适应不同的业务场景,增强了系统的灵活性和扩展性。
实际应用代码示例
// 抽象策略
interface PaymentStrategy {
void pay(double amount);
}
// 具体策略
class CreditCardPayment implements PaymentStrategy {
private String cardNumber;
private String expirationDate;
private String cvv;
public CreditCardPayment(String cardNumber, String expirationDate, String cvv) {
this.cardNumber = cardNumber;
this.expirationDate = expirationDate;
this.cvv = cvv;
}
@Override
public void pay(double amount) {
System.out.println("Paid " + amount + " using Credit Card. Card Number: " + cardNumber);
}
}
class PayPalPayment implements PaymentStrategy {
private String email;
private String password;
public PayPalPayment(String email, String password) {
this.email = email;
this.password = password;
}
@Override
public void pay(double amount) {
System.out.println("Paid " + amount + " using PayPal. Email: " + email);
}
}
// 上下文类
class ShoppingCart {
private PaymentStrategy paymentStrategy;
public void setPaymentStrategy(PaymentStrategy paymentStrategy) {
this.paymentStrategy = paymentStrategy;
}
public void checkout(double amount) {
paymentStrategy.pay(amount);
}
}
// 测试代码
public class ECommerceApp {
public static void main(String[] args) {
ShoppingCart cart = new ShoppingCart();
cart.setPaymentStrategy(new CreditCardPayment("1234567890123456", "12/25", "123"));
cart.checkout(50.0);
cart.setPaymentStrategy(new PayPalPayment("user@example.com", "password"));
cart.checkout(30.0);
}
}