当前位置:网站首页>Software architecture design principles
Software architecture design principles
2022-06-22 11:57:00 【A rare meal with coke】
One 、 Opening and closing principle
Definition : The opening and closing principle refers to a software entity ( Such as class 、 Modules and functions ) Because it should be open to expansion , Turn off for changes , The so-called opening and closing , It's also a principle for expanding and modifying two behaviors . It emphasizes building a framework with abstraction , Extend details with implementation , It can improve the reusability and maintainability of software system . Open close principle is the most basic design principle in object-oriented design , It teaches us how to build stability 、 Flexible systems . For example, version update , We try not to modify the source code , But you can add new features .
Example :
First, create a course class interface ICourse:
public interface ICourse {
Integer getId();
String getName();
Double getPrice();
}
Next, create a Java Structure the class of the course JavaCourse:
public class JavaCourse implements ICourse {
private Integer Id;
private String name;
private Double price;
public JavaCourse(Integer id, String name, Double price) {
Id = id;
this.name = name;
this.price = price;
}
@Override
public Integer getId() {
return this.Id;
}
@Override
public String getName() {
return this.name;
}
@Override
public Double getPrice() {
return this.price;
}
}
When the course does activities , The price needs to be modified , Obviously for the source code JavaCourse Class getPrice() There are certain risks in method modification , Applications that may affect other functions . The way to deal with this is to write a class that handles the preference logic JavaDiscountCourse. This preferential function is realized through inheritance .
public class JavaDiscountCourse extends JavaCourse {
public JavaDiscountCourse(Integer id, String name, Double price) {
super(id, name, price);
}
public Double getOriginPrice(){
return super.getPrice();
}
public Double getPrice(){
return super.getPrice()*0.61;
}
}
Two 、 The principle of Dependence Inversion
Definition : Dependency inversion principle refers to the design of code structure , High level modules should not rely on low level modules , Both depend on their abstractions , Abstraction should not depend on details , Details should depend on abstraction . By relying on inversion , You can reduce the coupling between classes , Improve the stability of the system , Improve code readability and maintainability , And it can reduce the risk of modifying the program .
Example : With Course Course as an example , Let's create a Tom class :
public class Tom {
public void studyJavaCourse(){
System.out.println("Tom I'm learning java");
}
public void studyPythonCourse(){
System.out.println("Tom I'm learning Python");
}
}
Next, call
public static void main(String[] args) {
Tom tom = new Tom();
tom.studyJavaCourse();
tom.studyPythonCourse();
}
When Tom When learning is addictive , When you want to study other courses , Then it is necessary to modify the bottom layer to the top layer in turn ( Call layer ) Code for , Obviously, this is very unstable after the system is released , It also brings unexpected risks .
Let's optimize the code , Create an abstraction of the course ICourse Interface :
public interface ICourse {
void study();
}
To write JavaCourse class :
public class JavaCourse implements ICourse{
@Override
public void study() {
System.out.println("Tom learning java");
}
}
To write PythonCourse class :
public class PythonCourse implements ICourse {
@Override
public void study() {
System.out.println("Tom learning Python");
}
}
new Tom class :
public class NewTom {
public void study(ICourse course){
course.study();
}
}
Next call :
public static void main(String[] args) {
NewTom newTom = new NewTom();
newTom.study(new JavaCourse());
newTom.study(new PythonCourse());
}
There are also different ways to inject , Also called dependency injection :
Constructor injection and implementation :
public class NewTom {
private ICourse course;
public NewTom(ICourse course) {
this.course = course;
}
public void study(ICourse course){
course.study();
}
public static void main(String[] args) {
NewTom newTom = new NewTom(new JavaCourse());
NewTom newTom2 = new NewTom(new PythonCourse());
}
}
Setter Inject :( Apply to when Tom Is a global singleton )
public class NewTom {
private ICourse course;
public void setCourse(ICourse course) {
this.course = course;
}
public void study(){
course.study();
}
public static void main(String[] args) {
NewTom newTom = new NewTom();
newTom.setCourse(new JavaCourse());
newTom.study();
newTom.setCourse(new PythonCourse());
newTom.study();
}
}
3、 ... and 、 Principle of single responsibility
Definition : Do not have more than one reason for class changes . Suppose we have a class with two responsibilities , Once there is a requirement change , Modify the logic code of one of the responsibilities , May cause the function of another responsibility to fail . thus , There are two reasons for the change of this class .
Solution : Implement the two responsibilities with two classes , Decoupling . Later requirements change and maintenance will not affect each other .
effect : Reduce class complexity , Improve the readability of the class , Improve the maintainability of the system , Reduce the risk of change .
Four 、 Interface isolation principle
Definition : The principle of interface isolation is to use multiple special interfaces , Instead of using a single master interface , Customers should not rely on interfaces they do not need , This principle guides us to pay attention to when designing interfaces :
- One dependency on another should be based on the smallest interface .
- Establish a single interface , Don't build massive interfaces .
- Refine the interface as much as possible , Minimal methods in the interface .
Code :
IAnimal The code is as follows :
public interface IAnimal {
void eat();
void fly();
void swim();
}
Bird The class code is as follows :
public class Bird implements IAnimal {
@Override
public void eat() {
}
@Override
public void fly() {
}
@Override
public void swim() {
}
}
Dog The class code is as follows :
public class Dog implements IAnimal {
@Override
public void eat() {
}
@Override
public void fly() {
}
@Override
public void swim() {
}
}
In the above code ,Bird Of swin() The method may only be empty , but Dog Medium fiy() The method is obviously impossible . At this point, you need to design different interfaces :
IEatAnimal :
public interface IEatAnimal {
void eat();
}
IFlyAnimal :
public interface IFlyAnimal {
void fly();
}
ISwimAnimal :
public interface ISwimAnimal {
void swim();
}
Dog Class code :
public class Dog implements ISwimAnimal,IEatAnimal {
@Override
public void eat() {
}
@Override
public void swim() {
}
}
5、 ... and 、 The Demeter principle
It means that the object should have the least understanding of other objects , Also known as the least known principle , Minimize the coupling between classes . The Dimiter principle emphasizes mainly : To communicate with friends , Don't talk to strangers .
Now let's design a permission system ,BOSS Need to see the number of courses currently posted online , This is the time ,BOSS To find the TeamLeader Go and count ,TeamLeader Tell the statistics to BOSS. Next, let's look at the code .
Course:
public class Course {
}
TeamLeader:
public class TeamLeader {
public void cheakNumberOfCourses(List<Course> courses){
System.out.println(" Currently, the published courses are :"+ courses.size());
}
}
Boss:
public class Boss {
public void commandCheckNumber(TeamLeader teamLeader){
List<Course> courseList = new ArrayList<>();
for (int i = 0; i < 20; i++) {
courseList.add(new Course());
}
teamLeader.cheakNumberOfCourses(courseList);
}
}
Test code :
public static void main(String[] args) {
Boss boss = new Boss();
TeamLeader teamLeader = new TeamLeader();
boss.commandCheckNumber(teamLeader);
}
According to the code above ,Boss Just want to know the result , You don't need to follow Course Direct communication , and TeamLeader Statistics need to quote Course object . Next, code improvements :
public class TeamLeader {
public void cheakNumberOfCourses(){
List<Course> courseList = new ArrayList<>();
for (int i = 0; i < 20; i++) {
courseList.add(new Course());
}
System.out.println(" Currently, the published courses are :"+ courseList.size());
}
}
public class Boss {
public void commandCheckNumber(TeamLeader teamLeader) {
teamLeader.cheakNumberOfCourses();
}
}
6、 ... and 、 Richter's principle of substitution
It means if for each type T1 The object of O1, All of them are of type T2 The object of O2, So that T1 All programs defined P In all objects O1 Are replaced with O2 when , Program P There is no change in the behavior of , So the type T2 It's the type T1 Subtypes of .
in other words :
- Subclasses can implement Frey's abstract methods , But you cannot override non-abstract methods of a parent class .
- Subclasses can add their own unique methods .
- When a method of a house class overloads a method of a parent class , Method preconditions ( Input of both methods / Enter the reference ) More relaxed than the input parameters of the parent method .
- When a method of a subclass implements a method of a parent class ,( rewrite / Overloading or implementing abstract methods ), The postcondition of the method ( The output of the method / Put return value ) More stringent than or the same as the parent .
advantage :
- Constraint inheritance is rampant , It is an embodiment of the open close principle .
- Enhance the robustness of the program , At the same time, it can be very compatible when changing , Very high program maintainability and scalability , Reduce the risk of requirements changes .
7、 ... and 、 Synthetic multiplexing principle
It means to use object combination as much as possible / Aggregation rather than inheritance can achieve the purpose of software reuse , The system can be more flexible , Reduce the coupling between classes , Changes in one class have relatively little impact on other classes .
边栏推荐
- SPI 与 API的区别
- 奋斗吧,程序员——第四十八章 千金纵买相如赋,脉脉此情谁诉
- 奋斗吧,程序员——第四十章 一面风情深有韵,半笺娇恨寄幽怀
- HMS Core新闻行业解决方案:让技术加上人文的温度
- Solution to 94d problem of Niuke practice match
- haas506 2.0开发教程-高级组件库-modem.info(仅支持2.2以上版本)
- KNN classification of MATLAB (with source code) is used to realize pixel classification (set the proportion of training set by yourself) and print test accuracy
- Solution to 55e of Niuke challenge
- Redis - 11、集群(Cluster)
- IO操作案例合集
猜你喜欢

Niuke challenge 53c

鉴权之cookie、session、JWT

Duanyongping, the "Buffett of China": a wise investment

Redis - 9、持久化之AOF(Append OnlyFile)

Matlab的KNN分类使用(附源码),实现像素分类(自己设置训练集比例),打印测试精度

Solution to 55e of Niuke challenge

【软工】获取需求

APM flight mode switching -- source code explanation

1.11 haas506 2.0开发教程-driver-RTC(仅支持2.2以上版本)

Configure the GPU version of pytorch and torchvision, and learn the GPU version of torch step
随机推荐
IO之ByteStream案例
奋斗吧,程序员——第四十七章 所谓伊人,在水一方
KNN classification of MATLAB (with source code) is used to realize pixel classification (set the proportion of training set by yourself) and print test accuracy
The R language uses the matchit package for propensity matching analysis and match The data function constructs the matched sample set, and uses visual analysis to test the balance of all covariates i
软件架构设计原则
牛客挑战赛53C
Three transition schemes from IPv4 to IPv6
General graph maximum matching (with flower tree) template
Solution to the 55D problem of Niuke challenge
Security risks exist in open source code: an average of 49 vulnerabilities exist in a project
把蔚来告上法庭,奥迪急什么?
[Software Engineering] Introduction & process and life cycle modeling
More than half of 2022, no new air outlet
成功案例 | 安超云助力兰州大学第二医院搭建新型IT基础设施平台 提升医疗信息资源利用率
Reader case of IO
sql注入绕过方法总结
奋斗吧,程序员——第四十四章 八百里分麾下炙,五十弦翻塞外声
Redis - 5、Jedis操作Redis6
Getting to know elastricearch
Struggle, programmer chapter 38 in the old days, when the road turned to the edge of the forest, I suddenly saw