面向对象编程原则_学习面向对象编程的扎实原则

面向对象编程原则

Object-oriented programming (or OOP) is a style of programming that encapsulates data and behaviors into models known as objects. In this way, related code is grouped together and kept separate from other code, and provides reusable blocks that can be used to rationalise the problem at hand.

面向对象编程(或OOP)是一种编程样式,它将数据和行为封装到称为对象的模型中。 通过这种方式,相关的代码被组合在一起并与其他代码分开,并提供了可重用的块,这些块可用于合理化当前的问题。

OOP is probably one of the most common forms programming, and many popular programming languages, including C#, Java, and JavaScript, are built with this in mind.

OOP可能是最常见的形式编程之一,并且在此基础上构建了许多流行的编程语言,包括C#,Java和JavaScript。

In a lot of languages, the blueprint for the object is known as a class. The class contains all the definitions for that object, including properties and functions (more commonly known as methods).

在许多语言中,对象的蓝图称为类。 该类包含该对象的所有定义,包括属性和函数(通常称为方法)。

To create an actual object, we say that we create an instance of the class, in which all of the property definitions are given actual values. Importantly, we can have multiple instances of the same class existing at the same time, each with different values.

要创建一个实际的对象,我们说我们创建了一个类的实例,在该实例中,所有属性定义都被赋予了实际值。 重要的是,我们可以同时存在同一类的多个实例,每个实例具有不同的值。

For example, we could create a simple Person class that has a name property and a speak method:

例如,我们可以创建一个简单的Person类,该类具有name属性和一个talk方法:

This is the blueprint. Now we can create two separate instances of the class, and the speak methods will give different outputs because each actual object is instantiated with a different value for the name property.

这是蓝图。 现在,我们可以创建该类的两个单独的实例,speak方法将提供不同的输出,因为每个实际对象都使用不同的name属性值实例化。

var bernard = new Person("Bernard");
var sally = new Person("Sally");bernard.Speak();
sally.Speak();

Although these are very simple examples, hopefully you can see the benefit of being able to create these object blueprints and create separate instances of actual objects.

尽管这些都是非常简单的示例,但希望您能看到能够创建这些对象蓝图并创建实际对象的单独实例的好处。

However, it can be easy to misuse objects and create difficult-to-read or unstable code, if you’re not careful. For example, you could potentially end up with a “God” class that has lots of unrelated behaviour crammed into the same object.

但是,如果不注意的话,很容易滥用对象并创建难以阅读或不稳定的代码。 例如,您可能最终会遇到“上帝”类,该类中有很多无关的行为塞在同一个对象中。

To help write good, maintainable, stable code, the SOLID principles have been described below.

为了帮助编写好的,可维护的,稳定的代码,下面描述了SOLID原理。

  • S — Single responsibility principle

    S-单一责任原则

  • O — Open/closed principle

    O —打开/关闭原理

  • L — Liskov substitution principle

    L — Liskov替代原理

  • I — Interface segregation principle

    I —接口隔离原理

  • D — Dependency inversion principle

    D —依赖倒置原则

S-单一责任原则(S — Single Responsibility Principle)

The title here is pretty self-explanatory. A class should only have one responsibility. This is to avoid the “God” class scenario, where one class does everything, and helps split up your code into smaller, sensible chunks.

这里的标题很不言自明。 一堂课只有一个责任。 这是为了避免出现“上帝”类情况,在这种情况下,一个类可以完成所有工作,并有助于将您的代码拆分为较小的,有意义的块。

Although the single responsibility principle, is quite easy to understand, in practice it is not always so simple to spot when something belongs in a class and when it should be moved to a different class. Making this judgement is mostly a matter of experience, and you will get better at it with time.

尽管单责任原则很容易理解,但实际上,找出某物何时属于某个班级以及何时将其移至另一个班级并不总是那么容易。 做出此判断主要是经验问题,随着时间的推移,您会变得更好。

If we go back to our Person class, we might decide that we want to save each person into a database. Therefore, it might seem sensible to create a method on the Person class:

如果返回到Person类,我们可能会决定将每个人保存到数据库中。 因此,在Person类上创建一个方法似乎是明智的:

However, the problem here is that the details of how to save a person to the database is an additional responsibility, and so that responsibility should be moved to another class.

但是,这里的问题在于,如何将人保存到数据库的详细信息是一项附加责任,因此应将责任移至另一类。

Therefore, we could create a database class, with a SavePerson method, and pass the instance of the Person into that class. That way the Person class only deals with the details of the person, and the database class deals with the details of saving the person.

因此,我们可以使用SavePerson方法创建数据库类,并将Person的实例传递到该类中。 这样,Person类仅处理人员的详细信息,而数据库类处理保存人员的详细信息。

O —打开/关闭原理 (O — Open/closed principle)

The open/closed principle states that an object should be open for extension but closed for modification. This means that you should design you objects in such a way that they can be easily extended, without having to directly modify them.

打开/关闭原理指出,对象应打开以进行扩展,但应关闭以进行修改。 这意味着您应以易于扩展对象的方式设计对象,而不必直接对其进行修改。

For example, we could define two new classes, Employee and Manager, which are derived from the Person class, and a SalaryCalculator class.

例如,我们可以定义两个新类,Employee和Manager,它们是从Person类派生的,以及一个SalaryCalculator类。

In this example, the SalaryCalculator class violates the open/closed principle because, if we extend the program by adding a Director class, we would have to modify the CalculateSalary method to account for this.

在此示例中,SalaryCalculator类违反了打开/关闭原则,因为如果通过添加Director类扩展程序,则必须修改CalculateSalary方法以解决此问题。

To fix this, we could add a DailyRate property to each of the Person types. That way, we can add as many Person types as we want, and never have to modify SalaryCalculator.

要解决此问题,我们可以向每种Person类型添加DailyRate属性。 这样,我们可以根据需要添加任意数量的Person类型,而无需修改SalaryCalculator。

L — Liskov替代原理 (L — Liskov substitution principle)

The Liskov substitution principle states that every sub-class should be substitutable for it’s base class and the program will still behave as expected.

Liskov替换原则指出,每个子类都可以替换为其基类,并且程序仍将按预期运行。

The example for the open/closed principle is also a good example for the Liskov substitution principle.

打开/关闭原理的示例也是Liskov替代原理的很好的示例。

In the SalaryCalculator class, the method takes the base class Person but at runtime we can pass any of its sub-classes too. Because we have used the virtual and override keywords in the Person and sub-classes respectively, the value of the DailyRate inside the CalculateSalary method will be that of the sub-class i.e even though we have substituted the sub-classes for the base class in the CalculateSalary method, the method still behaves correctly.

在SalaryCalculator类中,该方法采用基类Person,但在运行时,我们也可以传递其任何子类。 因为我们分别在Person和子类中使用了virtual和override关键字,所以CalculateSalary方法中DailyRate的值将是该子类的值,即,即使我们用以下子类替换了基类: CalculateSalary方法,该方法仍然可以正常运行。

As an example of violating the Liskov substitution principle, we could redefine our classes as:

作为违反Liskov替换原理的示例,我们可以将类重新定义为:

With this definition we violate the Liskov substitution principle because the DailyRate will always evaluate to 0 in the SalaryCalculator and not the value of the sub-class.

使用此定义,我们违反了Liskov替换原则,因为DailyRate在SalaryCalculator中始终评估为0,而不是子类的值。

I —接口隔离原理 (I — Interface segregation principle)

The interface segregation principle states that a client should not be forced to implement properties and methods of an interface that it will not use. Therefore, it is better to define lots of small, specific interfaces, rather than few large, general interfaces.

接口隔离原则指出,不应强迫客户端实现将不使用的接口的属性和方法。 因此,最好定义很多小的特定接口,而不是几个大的通用接口。

As an example, we could define an IRepository interface for performing CRUD operations for our Person class on a database and implement it:

例如,我们可以定义一个IRepository接口,以对数据库上的Person类执行CRUD操作并实现它:

This is fine if we know that we will always need full CRUD functionality. But what if actually, we only require the repository to be readonly? At the minute, we’re forced to implement the full CRUD operations, even if we don’t need them.

如果我们知道我们将始终需要完整的CRUD功能,那就很好。 但是,如果实际上,我们仅要求存储库为只读怎么办? 在这一刻,我们被迫实施完整的CRUD操作,即使我们不需要它们也是如此。

Instead we can define multiple interfaces, and only implement the ones that we need.

相反,我们可以定义多个接口,而仅实现所需的接口。

Then we can optionally choose to make a implement readonly repository or a full CRUD repository.

然后,我们可以选择将工具实现只读存储库或完整的CRUD存储库。

D —依赖倒置原则 (D — Dependency Inversion principle)

The dependency inversion principle states that classes shouldn’t depend on other classes, but instead should depend on the interfaces that those classes implement. This has the effect of inverting the direction of dependencies.

依赖关系反转原则指出,类不应依赖于其他类,而应依赖于这些类实现的接口。 这具有反转依赖方向的效果。

For example, a traditional 3-tier app consisting of only classes might have a PersonPresenter class, which depends on a PersonLogic class, which depends on a PersonRepository class. E.g.

例如,仅由类组成的传统3层应用程序可能具有PersonPresenter类,该类取决于PersonLogic类,而PersonLogic类取决于PersonRepository类。 例如

PersonPresenter --> PersonLogic --> PersonRepository

The problem with this is that it tightly couples the high level presentation to the low level implementation details. It’s much better to have loosely coupled code, which can be achieved using interfaces.

这样做的问题在于,它会将高层的展示与底层的实现细节紧密地结合在一起。 拥有松散耦合的代码更好,这可以使用接口来实现。

To invert the dependencies, we can create interfaces of each of the low level classes, and have those classes implement them:

为了反转依赖关系,我们可以创建每个低级类的接口,并让这些类实现它们:

PersonPresenter --> IPersonLogic IPersonRepository

结论 (Conclusion)

So there are the 5 SOLID principles of Object Oriented Programming. If you’ve found it useful, please like and share this post. And feel free to follow me on Twitter: @dr_sam_walpole

因此,存在面向对象编程的5条SOLID原理。 如果您发现它有用,请喜欢并分享这篇文章。 并随时在Twitter上关注我: @dr_sam_walpole

Originally published at https://samwalpole.com.

最初发布在https://samwalpole.com

翻译自: https://medium.com/swlh/learn-the-solid-principles-for-object-oriented-programming-bfd391937b31

面向对象编程原则

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值