开放-封闭原则

定义

开放-封闭原则,是说软件实体(类、模块、函数等)应该可以扩展,但是不可修改,一旦软件实体发布,其源代码就不应该被修改来改变其行为。这有助于减少因修改既有功能而引入新错误的风险。

举一个简单的例子,假设有一个绘图程序,它可以绘制不同种类的形状。如果遵循开放封闭原则,我们应该设计一个基本的形状类(如Shape),然后为每种具体的形状创建继承自Shape的子类(如CircleSquare等)。当需要添加新形状时,我们只需添加一个新的子类而不需要修改现有的类。这样,绘图程序对新形状的扩展是开放的,但对现有代码的修改是封闭的。

为什么使用开放-封闭原则

主要为了下面的目的

  1. 提高软件系统的可维护性:当需要改变或添加新功能时,可以通过添加新代码而不是修改现有代码,从而减少对现有系统的影响。

  2. 增强软件系统的可扩展性:系统设计为易于扩展(新增新功能往往只需要新增子类就可以不需要修改代码逻辑),可以适应未来的变化和需求。

  3. 促进代码的重用:设计灵活、可扩展的组件可以在不同的环境中重用(比如新增一个圆形别的地方也能使用)。

代码案例

假设我们正在开发一个简单的支付系统,可以处理不同类型的支付方式,如信用卡支付、PayPal支付等。为了遵守开放封闭原则,我们将设计系统的方式使得它可以轻松添加新的支付方式,而无需修改现有代码。

步骤 1: 定义一个支付接口

首先,我们定义一个支付接口(Payment),所有的支付方式都必须实现这个接口。

public interface Payment {
    void processPayment(double amount);
}

步骤 2: 实现具体的支付方式

然后,我们为每种支付方式实现一个类,这些类都实现了Payment接口。

public class CreditCardPayment implements Payment {
    @Override
    public void processPayment(double amount) {
        System.out.println("Processing credit card payment of $" + amount);
    }
}

public class PayPalPayment implements Payment {
    @Override
    public void processPayment(double amount) {
        System.out.println("Processing PayPal payment of $" + amount);
    }
}

步骤 3: 创建支付处理类

接下来,我们创建一个支付处理类,它接受Payment接口的实例。这个类不需要知道具体的支付细节,只需要调用processPayment方法。

public class PaymentProcessor {
    public void process(double amount, Payment paymentMethod) {
        paymentMethod.processPayment(amount);
    }
}

如何遵循开放封闭原则

现在,如果我们想要添加一种新的支付方式,比如比特币支付,我们只需要添加一个新的类实现Payment接口。这样,我们就扩展了功能而不需要修改现有的PaymentProcessor类或其他支付类。

public class BitcoinPayment implements Payment {
    @Override
    public void processPayment(double amount) {
        System.out.println("Processing Bitcoin payment of $" + amount);
    }
}

使用示例

现在,我们可以在系统中使用不同的支付方式,而无需修改现有代码。

public class Main {
    public static void main(String[] args) {
        PaymentProcessor processor = new PaymentProcessor();

        Payment creditCardPayment = new CreditCardPayment();
        processor.process(100.0, creditCardPayment);

        Payment payPalPayment = new PayPalPayment();
        processor.process(200.0, payPalPayment);

        Payment bitcoinPayment = new BitcoinPayment();
        processor.process(300.0, bitcoinPayment);
    }
}

通过定义一个共同的接口Payment并让所有支付方式实现这个支付处理类(PaymentProcessor)对于添加新的支付方式是开放的,但对于修改是封闭的。这样的设计遵循了开放封闭原则,提高了代码的可维护性和扩展性。

反例

同样是支付处理类PaymentProcessor

public class PaymentProcessor {
    public void processPayment(String type, double amount) {
        if (type.equals("CreditCard")) {
            // 信用卡支付逻辑
            System.out.println("Processing credit card payment of $" + amount);
        } else if (type.equals("PayPal")) {
            // PayPal支付逻辑
            System.out.println("Processing PayPal payment of $" + amount);
        }
        // 对于每种新的支付方式,我们需要在这里添加新的else if块
    }
}

这里将支付逻辑放在一个单一的类中,而不是使用接口和多态,
如果我们想要添加比特币支付,我们必须修改PaymentProcessor类:

public void processPayment(String type, double amount) {
    if (type.equals("CreditCard")) {
        // 信用卡支付逻辑
        System.out.println("Processing credit card payment of $" + amount);
    } else if (type.equals("PayPal")) {
        // PayPal支付逻辑
        System.out.println("Processing PayPal payment of $" + amount);
    } else if (type.equals("Bitcoin")) {
        // 比特币支付逻辑
        System.out.println("Processing Bitcoin payment of $" + amount);
    }
}

对比之前的

public class PaymentProcessor {
    public void process(double amount, Payment paymentMethod) {
        paymentMethod.processPayment(amount);
    }
}

这里的缺点显而易见

  1. 不易扩展:如果我们想添加一种新的支付方式,比如比特币支付,我们必须修改PaymentProcessor类,添加新的else if块。这违反了开放封闭原则,因为我们需要修改现有的代码来扩展功能。

  2. 不易维护:随着支付方式的增加,PaymentProcessor类将变得越来越复杂,越来越难以维护。每次添加或修改支付逻辑时,都有引入错误的风险。

  3. 违反单一责任原则PaymentProcessor类处理了所有类型的支付逻辑,这违反了单一责任原则。一个类应该只负责一个功能领域内的责任。

你可能感兴趣的:(设计模式,java)