一:单一职责原则
一个类或者一个模块只完成一个功能
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<Handler> 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 规范。