1. 引入SOLID原则步骤
单一职责原则(SRP)
- 分析与拆分:审查现有类,确定每个类所承担的多个职责。例如,一个类既处理用户认证逻辑,又负责订单处理。将其拆分为
UserAuthentication
类专注于认证,OrderProcessor
类负责订单相关操作。
- 代码重构:把相关方法和数据从原类迁移到新类,确保每个类仅有一个明确的职责。
开闭原则(OCP)
- 抽象与扩展:识别可能变化的部分,通过抽象(如接口或抽象类)进行封装。以电商系统的促销策略为例,定义
PromotionStrategy
接口,包含calculateDiscount
方法。
- 实现具体策略:针对不同促销策略(如满减、折扣)创建实现该接口的具体类,如
FullReductionPromotion
和DiscountPromotion
。这样在新增促销策略时,无需修改原有代码,只需创建新的实现类。
里氏替换原则(LSP)
- 确保继承正确性:检查继承关系,确保子类可以完全替换父类。比如
Square
类继承Rectangle
类,需保证Square
对象在任何使用Rectangle
对象的地方都能正常工作。如果Rectangle
有设置宽和高的方法,Square
在重写时要保证设置宽高的行为符合Square
的定义(即宽高相等)。
- 修正违反情况:若发现子类行为与父类不一致,考虑重新设计继承结构,如使用组合代替继承。
接口隔离原则(ISP)
- 拆分臃肿接口:找出包含过多方法的接口,将其拆分为多个专用接口。例如,一个
Employee
接口包含work
、manage
、report
等方法,对于普通员工和经理可能不需要全部方法。可以拆分为Worker
接口(包含work
方法)、Manager
接口(包含manage
和report
方法)。
- 类实现专用接口:让类只实现其需要的接口,减少不必要的依赖。
依赖倒置原则(DIP)
- 依赖抽象而非具体:在高层模块中,依赖抽象类或接口,而不是具体实现类。例如,一个
PaymentService
类依赖PaymentGateway
接口,而不是具体的AlipayGateway
或WeChatPayGateway
类。
- 通过构造函数或方法注入:在创建
PaymentService
实例时,通过构造函数或方法参数传入具体的PaymentGateway
实现类,实现依赖注入。
2. 结合设计模式重构
策略模式
- 应用场景:用于解决系统中算法多变的问题,如上述电商系统的促销策略。
- 实现方式:定义策略接口,创建具体策略类实现接口,在需要使用策略的地方注入具体策略对象。例如:
// 策略接口
public interface PromotionStrategy {
double calculateDiscount(double price);
}
// 具体策略类1
public class FullReductionPromotion implements PromotionStrategy {
@Override
public double calculateDiscount(double price) {
// 满减逻辑
return price > 100? price - 20 : price;
}
}
// 具体策略类2
public class DiscountPromotion implements PromotionStrategy {
@Override
public double calculateDiscount(double price) {
// 折扣逻辑
return price * 0.8;
}
}
// 使用策略的类
public class Order {
private PromotionStrategy promotionStrategy;
public Order(PromotionStrategy promotionStrategy) {
this.promotionStrategy = promotionStrategy;
}
public double calculateTotalPrice(double originalPrice) {
return promotionStrategy.calculateDiscount(originalPrice);
}
}
装饰器模式
- 应用场景:当需要在运行时给对象添加新功能时使用。例如,给
Logger
类添加加密功能。
- 实现方式:定义抽象组件(如
Logger
接口),具体组件类(如FileLogger
实现Logger
接口),抽象装饰器类继承抽象组件类并持有抽象组件的引用,具体装饰器类继承抽象装饰器类并实现新增功能。例如:
// 抽象组件
public interface Logger {
void log(String message);
}
// 具体组件
public class FileLogger implements Logger {
@Override
public void log(String message) {
System.out.println("Logging to file: " + message);
}
}
// 抽象装饰器
public abstract class LoggerDecorator implements Logger {
protected Logger logger;
public LoggerDecorator(Logger logger) {
this.logger = logger;
}
@Override
public void log(String message) {
logger.log(message);
}
}
// 具体装饰器
public class EncryptedLoggerDecorator extends LoggerDecorator {
public EncryptedLoggerDecorator(Logger logger) {
super(logger);
}
@Override
public void log(String message) {
String encryptedMessage = encrypt(message);
super.log(encryptedMessage);
}
private String encrypt(String message) {
// 加密逻辑
return new StringBuilder(message).reverse().toString();
}
}
3. 权衡设计模式对系统的影响及优化策略
性能影响及优化
- 策略模式:每次切换策略可能会创建新的策略对象,增加对象创建开销。优化策略是使用策略对象池,复用已创建的策略对象,减少对象创建频率。
- 装饰器模式:多层装饰可能导致方法调用链变长,影响性能。可以通过缓存装饰后的结果,避免重复计算。例如,在
EncryptedLoggerDecorator
中缓存加密后的消息。
资源占用影响及优化
- 策略模式:策略对象池会占用一定内存空间。可以设置对象池的最大容量,当超过容量时,采用合适的淘汰算法(如LRU)释放不再使用的策略对象。
- 装饰器模式:过多的装饰器类会增加代码体积和内存占用。合理规划装饰器结构,避免不必要的装饰,对于不常用的装饰功能,可以采用动态加载的方式,减少初始内存占用。