一个类或者一个模块只完成一个功能
- class UserInfo
- { userId, username, email, telephone}
对扩展开放,对修改关闭
- class Alert
- {
- void check(errorCount, duration)
- {
- if(errorCount > COUNT)
- notifiction.notify();
- if(duration > DURATION)
- notification.notify();
- }
- }
此时如果要增加一个tps峰值检测,就需要在Alert中添加,其次check的调用入参也需要更改,不符合“对修改关闭”的原则
可以这样:把errorCout和duration封装为class handler的子类,Alert中增加一个vector 数组,check()中轮询vector中数据,调用各handler子类的函数
伪代码如下:
- class AlertHandler
- {//基类
- public:
- AlertHandler(AlertRule r, Notification n) : rule(r), notification(n)
- {
-
- }
- void check() = 0;
-
- public:
- AlertRule rule;
- Notification notification;
- };
-
- Class ErrorCountHandler : public AlertHandler
- {
- public:
- void check(ApiStateInfo info)
- {
- if(info.getErrorCount() > rule.errorCount )
- {
- notification.notify("errorCount error!")
- }
- }
- };
-
- Class DurationHandler : public AlertHandler
- {
- public:
- void check(ApiStateInfo info)
- {
- if(info.getDuration() > rule.duration )
- {
- notification.notify("duration error!")
- }
- }
- };
- class Alert
- {
- public:
- vector
alterHandlers; - void addAlertHandler(AlertHandler handler)
- {
- alertHandlers.emplace_back(handler);
- }
- void check()
- {
- for(auto handler : alterHandlers)
- {//apiStateInfo为初始阈值
- handler.check(apiStateInfo);
- }
- }
- }
此时再新增一个告警监测只要继承AlertHandler,实现自己的check(),把TpsHandler 添加到Alert的vector即可,没有损坏原有结构,如下
- Class TpsHandler : public AlertHandler
- {
- public:
- void check(ApiStateInfo info)
- {
- if(info.tpsVal() > rule.tpsVal)
- {
- notification.notify("tpsValerror!")
- }
- }
- };
子类对象能够替换程序中的父类对象出现的任何地方,并且保证程序原有的逻辑不变以及正确性不被破坏
Clients should not be forced to depend upon interfaces that they do not use.
不应该强迫客户端去依赖它不需要的接口。 客户端是指接口调用者或使用者
例:
微服务用户系统提供了一组用户相关的API,如注册,登录,获取用户信息等,
- class UserInfo
- {
- void register(string cellphone, string passwd);
- void login(string cellphone, string passwd);
- void getUserInfoById(int userId);
- }
此时,后台管理系统要实现删除用户的功能,如果直接在上面UserInfo中添加deleteUserById(),会造成以下两点
应该把删除用户的接口单独封装,只提供给需要它的后台管理系统
- class UserInfo
- {
- void register(string cellphone, string passwd);
- void login(string cellphone, string passwd);
- void getUserInfoById(int userId);
- }
-
- class RetrictedUserService
- {
- bool deleteUserById(int userId);
- };
High-level modules shouldn’t depend on low-level modules. Both modules should depend on abstractions. In addition, abstractions shouldn’t depend on details. Details depend on abstractions.
我们将它翻译成中文,大概意思就是:高层模块(high-level modules)不要依赖低层模块(low-level)。高层模块和低层模块应该通过抽象(abstractions)来互相依赖。除此之外,抽象(abstractions)不要依赖具体实现细节(details),具体实现细节(details)依赖抽象(abstractions)。
例:
Tomcat 是运行 Java Web 应用程序的容器。我们编写的 Web 应用程序代码只需要部署在 Tomcat 容器下,便可以被 Tomcat 容器调用执行。按照之前的划分原则,Tomcat 就是高层模块,我们编写的 Web 应用程序代码就是低层模块。Tomcat 和应用程序代码之间并没有直接的依赖关系,两者都依赖同一个“抽象”,也就是 Sevlet 规范。Servlet 规范不依赖具体的 Tomcat 容器和应用程序的实现细节,而 Tomcat 容器和应用程序依赖 Servlet 规范。