石家庄做网站汉狮网络,哈尔滨快速建站点击查看,郑州男科医院排行哪家最好,软件项目外包平台一、单一职责原则#xff08;SRP#xff09; * 定义#xff1a;一个类应该只有一个引起它变化的原因。 * 解释#xff1a;意味着一个类应该专注于做一件事情#xff0c;当需求发生变化时#xff0c;只影响到一个类。这有助于降低类间的耦合#xff0c;使得代码更易于理…一、单一职责原则SRP * 定义一个类应该只有一个引起它变化的原因。 * 解释意味着一个类应该专注于做一件事情当需求发生变化时只影响到一个类。这有助于降低类间的耦合使得代码更易于理解和维护。 示例场景图书管理系统 假设我们正在设计一个图书管理系统的后端逻辑。在这个系统中我们需要处理图书的添加、删除、查询等功能同时也需要记录图书的借阅信息。 * 未按单一职责原则的示例
在这个实现中BookManager 类不仅负责图书的管理添加、删除、查询还负责图书借阅的记录。这意味着如果有需求变更比如需要改进图书借阅的逻辑那么这个类就需要改变同时图书的基本管理功能也可能受到影响。
public class BookManager
{private ListBook books;private Dictionaryint, BorrowRecord borrowRecords;public BookManager(){books new ListBook();borrowRecords new Dictionaryint, BorrowRecord();}public void AddBook(Book book){books.Add(book);}public void RemoveBook(int bookId){books.RemoveAll(b b.Id bookId);borrowRecords.Remove(bookId);}public Book GetBookById(int bookId){return books.FirstOrDefault(b b.Id bookId);}public void BorrowBook(int bookId, int userId){var book GetBookById(bookId);if (book ! null !borrowRecords.ContainsKey(bookId)){borrowRecords.Add(bookId, new BorrowRecord(bookId, userId));}}public void ReturnBook(int bookId){borrowRecords.Remove(bookId);}
}
* 按单一职责原则的示例
将归还和借阅的方法分解出来单独成一个类
public class BookRepository
{private ListBook books;public BookRepository(){books new ListBook();}public void AddBook(Book book){books.Add(book);}public void RemoveBook(int bookId){books.RemoveAll(b b.Id bookId);}public Book GetBookById(int bookId){return books.FirstOrDefault(b b.Id bookId);}
}public class BorrowService
{private Dictionaryint, BorrowRecord borrowRecords;public BorrowService(){borrowRecords new Dictionaryint, BorrowRecord();}public void BorrowBook(int bookId, int userId){if (!borrowRecords.ContainsKey(bookId)){borrowRecords.Add(bookId, new BorrowRecord(bookId, userId));}}public void ReturnBook(int bookId){borrowRecords.Remove(bookId);}
} 二、开放封闭原则OCP * 定义软件实体类、模块、函数等应该是可扩展的但是不可修改的。 * 解释当系统的需求发生变化时我们应该能够通过增加新的代码来扩展原有的功能而不是修改已有的代码。这有助于保持系统的稳定性减少因为修改现有代码带来的风险。 示例场景计算不同类型的订单折扣 假设我们正在开发一个电子商务平台需要为不同类型的订单计算折扣。最初我们的系统只支持两种类型的订单标准订单和批量订单其中批量订单可以享受额外的折扣。 * 未遵循开放封闭原则的示例:
public enum OrderType
{Standard,Bulk
}public class OrderDiscountCalculator
{public decimal CalculateDiscount(Order order){if (order.Type OrderType.Standard){return order.Total * 0.95m; // 标准订单95%的折扣}else if (order.Type OrderType.Bulk){return order.Total * 0.90m; // 批量订单90%的折扣}return order.Total;}
}
在这个实现中OrderDiscountCalculator 类直接在 CalculateDiscount 方法中根据订单类型计算折扣。如果未来需要添加新的订单类型比如会员订单我们需要修改这个方法这违反了OCP。
* 遵循开放闭合原则示例:
// 折扣策略接口
public interface IDiscountStrategy
{decimal CalculateDiscount(Order order);
}// 标准订单折扣策略
public class StandardOrderDiscount : IDiscountStrategy
{public decimal CalculateDiscount(Order order){return order.Total * 0.95m;}
}// 批量订单折扣策略
public class BulkOrderDiscount : IDiscountStrategy
{public decimal CalculateDiscount(Order order){return order.Total * 0.90m;}
}// 订单折扣计算器
public class OrderDiscountCalculator
{private readonly IDiscountStrategy _discountStrategy;public OrderDiscountCalculator(IDiscountStrategy discountStrategy){_discountStrategy discountStrategy;}public decimal CalculateDiscount(Order order){return _discountStrategy.CalculateDiscount(order);}
}
为了遵循OCP我们可以使用策略模式将折扣的计算逻辑封装到独立的策略类中然后在 OrderDiscountCalculator 中使用这些策略。
现在如果我们需要添加新的订单类型比如会员订单我们只需要实现 IDiscountStrategy 接口并创建一个新的策略类然后在应用中适当地使用它而不需要修改现有的 OrderDiscountCalculator 类。这样我们的系统就对扩展开放对修改封闭了。
为了在应用中使用这些策略你可以使用依赖注入框架根据订单类型动态地注入正确的策略实例。这种方式提高了代码的灵活性和可扩展性同时减少了修改现有代码的风险。 * 那么我们现在用依赖注入的方式实现 【遵循OCP的策略模式】 步骤1定义接口和策略类 我们已经定义了 IDiscountStrategy 接口和具体的策略类StandardOrderDiscount 和 BulkOrderDiscount这里不再重复。 步骤2配置依赖注入容器 public void ConfigureServices(IServiceCollection services)
{// 注册策略类services.AddTransientIDiscountStrategy, StandardOrderDiscount();services.AddTransientIDiscountStrategy, BulkOrderDiscount();// 可以继续注册更多策略类如会员订单策略// 注册 OrderDiscountCalculator 类它将依赖于策略类services.AddTransientOrderDiscountCalculator();
} 这里我们使用了 AddTransient 方法这意味着每次请求一个新的服务实例时都会创建一个新的实例。 步骤3选择正确的策略 为了让控制器能够根据订单类型选择正确的策略我们需要在创建 OrderDiscountCalculator 实例时传入正确的策略。这可以通过创建工厂方法或使用条件逻辑来实现。例如你可以创建一个 DiscountStrategyFactory 类它根据订单类型返回相应的策略实例。 public class DiscountStrategyFactory
{private readonly IServiceProvider _serviceProvider;public DiscountStrategyFactory(IServiceProvider serviceProvider){_serviceProvider serviceProvider;}public IDiscountStrategy GetStrategy(Order order){switch (order.Type){case OrderType.Standard:return _serviceProvider.GetRequiredServiceStandardOrderDiscount();case OrderType.Bulk:return _serviceProvider.GetRequiredServiceBulkOrderDiscount();// 可以添加更多case处理其他类型的订单default:throw new ArgumentException(Invalid order type.);}}
} 在控制器中根据订单类型选择正确的类 public class OrdersController : Controller
{private readonly DiscountStrategyFactory _strategyFactory;private readonly OrderDiscountCalculator _discountCalculator;public OrdersController(IServiceProvider serviceProvider){_strategyFactory new DiscountStrategyFactory(serviceProvider);_discountCalculator new OrderDiscountCalculator(_strategyFactory.GetStrategy(GetOrderById(orderId)));}// ...
} -------------------------------- ^.^ 写累了下次再写 ^.^--------------------------------- 三、里氏替换原则LSP * 定义子类必须能够替换其基类。 * 解释任何基类可以出现的地方子类一定可以出现。这保证了在使用继承时子类的行为与基类一致不会破坏程序的正确性 四、接口隔离原则ISP * 定义不应该强迫客户程序依赖于它们不用的方法。 * 解释一个类对另一个类的依赖应该建立在最小的接口上即不应该为实现接口而实现接口而是应该实现真正需要的方法。这有助于降低类间的耦合使得接口更纯粹更易于理解和使用。 五、依赖倒置原则DIP * 定义高层模块不应该依赖于低层模块二者都应该依赖于抽象抽象不应该依赖于细节细节应该依赖于抽象。 * 解释高层模块如业务逻辑层应依赖于抽象接口或基类而不是具体的实现类。这有助于解耦系统中的各个部分使得系统更灵活更易于扩展和维护。