架构设计模式—6大设计原则
架构设计是软件开发中非常重要的一环,良好的架构可以提高软件系统的可维护性、可扩展性和可重用性。在架构设计过程中,遵循一定的设计原则可以帮助我们构建合理的架构。 本文介绍6大常用的架构设计原则,他们是:
- 单一职责原则(Single Responsibility Principle, SRP) 单一职责原则要求一个类或模块只负责完成一项职责。这样可以降低模块之间的耦合性,提高模块的内聚性,使得系统更加灵活和可维护。
- 开放封闭原则(Open-Closed Principle, OCP) 开放封闭原则指的是软件实体(类、模块、函数等)在扩展时应该开放,而在修改时应该封闭。通过接口和抽象类来实现,可以让系统在不修改已有代码的情况下进行扩展。
- 里氏替换原则(Liskov Substitution Principle, LSP) 里氏替换原则要求子类型必须能够替换掉父类型,而不会影响程序的正确性。在使用继承时,必须确保子类可以替代父类并且能够正常工作。
- 依赖倒转原则(Dependency Inversion Principle, DIP) 依赖倒转原则要求高层模块不应该依赖于低层模块,而是应该依赖于抽象。通过引入接口和依赖注入等技术,降低模块之间的耦合性,提高系统的灵活性和可维护性。
- 接口隔离原则(Interface Segregation Principle, ISP) 接口隔离原则要求接口应该精简单一,不应该包含多余的方法。客户端不应该依赖于它不需要使用的接口。通过细化接口,可以降低客户端的依赖性,提高系统的灵活性。
- 迪米特法则(Law of Demeter, LoD) 迪米特法则要求一个对象应该对其他对象保持最少的了解,只和朋友交流,不和陌生人说话。对象之间的耦合性越低,系统的可维护性和可扩展性越高。 以上6大设计原则是架构设计过程中常用的准则,不同的原则可以结合使用,根据具体的应用场景进行选择。遵循这些原则可以帮助我们构建高质量的软件系统。
下面是一个简单的示例代码,使用了单一职责原则和依赖倒转原则:
代码语言:javascript复制javaCopy code// 单一职责原则示例
public class User {
private String name;
private String email;
public User(String name, String email) {
this.name = name;
this.email = email;
}
// 省略其他属性的getter和setter方法
public void sendEmail(String message) {
EmailService emailService = new EmailService();
emailService.sendEmail(this.email, message);
}
}
// EmailService负责邮件发送的逻辑
public class EmailService {
public void sendEmail(String emailAddress, String message) {
// 发送邮件的实现逻辑,这里省略具体实现
}
}
// 依赖倒转原则示例
public interface NotificationService {
void sendNotification(String message);
}
public class EmailNotificationService implements NotificationService {
@Override
public void sendNotification(String message) {
// 发送邮件通知的实现逻辑,这里省略具体实现
}
}
public class SMSNotificationService implements NotificationService {
@Override
public void sendNotification(String message) {
// 发送短信通知的实现逻辑,这里省略具体实现
}
}
public class NotificationManager {
private NotificationService notificationService;
public NotificationManager(NotificationService notificationService) {
this.notificationService = notificationService;
}
public void sendNotification(String message) {
notificationService.sendNotification(message);
}
}
在上面的示例中,User
类负责用户信息的管理,同时也负责向用户发送邮件。根据单一职责原则,User
类只负责完成用户信息管理的职责,具体的邮件发送逻辑交由 EmailService
类来实现。 另外,NotificationManager
类是一个通知管理器,根据依赖倒转原则,它依赖于 NotificationService
接口而不是具体的实现类。这样,我们可以通过传递不同的实现类(如 EmailNotificationService
或 SMSNotificationService
)来实现不同的通知方式。这样做可以降低代码的耦合性,提高系统的灵活性。
下面是一个简单示例代码,使用了开放封闭原则:
代码语言:javascript复制javaCopy codepublic interface Shape {
double calculateArea();
}
public class Rectangle implements Shape {
private double width;
private double height;
public Rectangle(double width, double height) {
this.width = width;
this.height = height;
}
@Override
public double calculateArea() {
return width * height;
}
}
public class Circle implements Shape {
private double radius;
public Circle(double radius) {
this.radius = radius;
}
@Override
public double calculateArea() {
return Math.PI * radius * radius;
}
}
public class AreaCalculator {
public double calculateTotalArea(List<Shape> shapes) {
double totalArea = 0;
for (Shape shape : shapes) {
totalArea = shape.calculateArea();
}
return totalArea;
}
}
在上面的示例中,我们定义了一个 Shape
接口,它包含了一个 calculateArea
方法来计算形状的面积。然后我们创建了两个形状的实现类 Rectangle
和 Circle
,它们都实现了 Shape
接口并提供了自己的面积计算逻辑。 接下来,我们创建了一个 AreaCalculator
类,它包含了一个 calculateTotalArea
方法,该方法接受一个 List<Shape>
参数,用于计算给定形状列表的总面积。这里的关键是,AreaCalculator
类对于形状的具体实现类是封闭的,不需要修改该类的代码。当我们需要添加新的形状时,只需创建新的实现类并实现 Shape
接口即可,无需修改 AreaCalculator
类。 例如,如果我们想添加一个新的形状,比如三角形,我们只需创建一个新的 Triangle
类并实现 Shape
接口即可,不需要修改 AreaCalculator
类的代码。这样就符合了开放封闭原则,系统对于扩展是开放的,对于修改是封闭的。这样设计的好处是,我们可以方便地添加新的形状,而不会影响到已有的代码功能。