理解面向对象编程
面向对象的世界引入了对象的概念,而这些对象又具有属性(数据成员)和方法(成员函数)。方法的作用就是处理属性。
对象:
- 对象表示开发应用内程序的实体
- 实体之间可以通过简单交互来解决现实世界的问题
类:
- 类可以帮助开发人员表示显示世界中的实体
- 类可以定义对象的属性和行为。属性是数据成员,行为由成员函数表示。
- 类包含了构造函数,构造函数的作用是为对象提供初始状态
- 类就像模板一样,非常易于重复使用
方法:
- 方法表示对象的行为
- 方法可以对属性进行处理,从而实现所需的功能
面向对象的主要概念
封装:
- 对象的行为对于外部世界来说是不可见的,或者说对象的状态信息是私密的
- 客户端不能通过直接操作来改变对象的内部状态。相反,客户端需要通过发送消息来请求对象改变其内部状态。对象可以根据请求的类型,通过特定的成员函数(例如get和set)改变它们的内部状态。
- 在python中,封装(数据和方法的隐藏)的概念不是隐式的,因为它没有提供
public
,private
,protected
等关键字 - 可以通过在变量名和方法名前面加
__
前缀,将属性变为私有
多态:
- 对象根据输入参数提供方法的不同实现
- 不同类型的对象可以使用相同的接口
- 对于python来说,多态是该语言的内置功能。例如
+
可以应用于整数之间,也可以应用于字符串和列表之间
继承:
- 继承表示一个类可以继承父类的大部分功能
- 继承被描述为一个重用基类中定义的功能并允许对原有功能进行独立扩展的选项
- 继承可以利用不同类的对象之间的关系建立层次结构
抽象:
- 它提供了一个简单的客户端接口,客户端可以通过该接口与类的对象进行交互,并可以调用该接口中定义的各个方法。
- 它将内部类的复杂性抽象为一个接口,这样客户端就不需要知道内部实现了。
在下面的例子中,我们通过 add ()方法对类 Adder 的内部细节进行了抽象处理:
class Adder:
def __init__(self):
self.sum = 0
def add(self, value):
self.sum += value
acc = Adder()
for i in range(99):
acc.add(i)
print(acc.sum)
组合:
- 它是一种将对象或类组合成更复杂的数据结构或软件实现的方法。
- 在组合中,一个对象可用于调用其他模块中的成员函数,这样一来,无需通过继承就可以实现基本功能的跨模块使用。
在下面的示例中,类 A 的对象被组合到了类 B 中:
class A(object):
def a1(self):
print("a1")
class B(object):
def b(self):
print("b")
A().a1()
objectB = B()
objectB.b()
面向对象的设计原则
开放封闭原则
开放/封闭原则规定,类或对象及其方法对于扩展来说,应该是开放的,但是对于修改来说,应该是封闭的。
这意味着当你开发软件应用的时候,一定确保以通用的方式来编写类或模块,以便每当需要扩展类或对象行为的时候不必修改类本身。相反,类的简单扩展将有助于建立新的行为。
优点:
- 现有的类不会被修改,因此退化的可能性较小。
- 它还有助于保持以前代码的向后兼容性
控制反转原则
控制反转原则是指,高层级的模块不应该依赖于低层级的模块,它们应该都依赖于抽象。细节应该依赖于抽象,而不是抽象依赖于细节。
该原则建议任何两个模块都不应以紧密方式相互依赖。事实上,基本模块和从属模块应当在它们之间提供一个抽象层来耦合。这个原则还建议,类的细节应该描绘抽象。在某些情况下,这种观念会反转,也就是实现细节本身决定了抽象,这种情况是应该避免的。
优点:
- 消弱了模块间的紧耦合,因此消除了系统中的复杂性/刚性
- 由于在依赖模块之间有一个明确的抽象层(由钩子或参数提供),因此便于通过更好的方式处理模块之间的依赖关系。
接口隔离原则
接口隔离原则规定,客户端不应该依赖于它们不需要使用的接口。
接口隔离原则的意思就是,软件开发人员应该仔细地处理接口。例如,它提醒开发人员/架构师开发的方法要与特定功能紧密相关。如果存在与接口无关的方法,那么依赖于该接口的类就必须实现它,实际上这是毫无必要的。
优点:
- 它强制开发人员编写“瘦身型”接口,并使方法与接口紧密相关。
- 防止向接口中随意添加方法。
单一职责原则
单一职责的含义是:类的职责单一,引起类变化的原因单一。
这个原则是说,当我们开发类时,它应该为特定的功能服务。如果一个类实现了两个功能,那么最好将它们分开。也就是说,功能才是改变的理由。
例如,一个类可以因为所需行为的变化而进行修改,但是如果一个类由于两个因素(基本上是两个功能的改变)而改变,那么该类就应该进行相应的分割。
优点:
- 每当一个功能发生变化时,除了特定的类需要改变外,其他类无需变动。
- 此外,如果一个类有多种功能,那么依赖它的类必定会由于多种原因而经历多次修改,这是应该避免的。
替换原则
替换原则规定,派生类必须能够完全取代基类。
这个原则很简单,当应用程序开发人员编写派生类时,该原则的含义就是他们应该扩展基类。此外,它还建议派生类应该尽可能对基类封闭,以至于派生类本身可以替换基类,而无需修改任何代码。
设计模式的概念
设计模式是由 GoF(Gang of Four)首先提出的,根据他们的观点,设计模式就是解决特定问题的解决方案。
设计模式的主要特点如下所示:
- 它们是语言无关的,可以用多种语言实现。
- 它们是动态的,随时会有新的模式引入
- 它们可以进行定制,因此对开发人员非常有用。
设计模式是已知问题的解决方案。因此,设计模式在分析或设计阶段非常有用,并且如预期的那样,在开发阶段也非常有用,因为它们与应用的编程直接相关。
设计模式的优点如下所示:
- 它们可以在多个项目中重复使用。
- 问题可以在架构级别得到解决。
- 它们都经过了时间的验证和良好的证明,是开发人员和架构师的宝贵经验。
- 它们具有可靠性和依赖性。
常用术语
代码段:用某种语言编写的一段具有特定用途的代码,例如,它可以是 Python 中的 DB 连接代码。
设计:用来解决某个特定问题的优秀解决方案。
标准:这是一种解决某类问题的方法,它非常通用,并且适用于当前的情况
模式:这是一个经过时间考验的、高效、可扩展的解决方案,能够解决一类已知问题。
上下文 — 设计模式的适用性
为了有效地使用设计模式,应用程序开发人员必须了解设计模式所适用的上下文。我们可以将上下文分为以下几种主要类型。
- 参与者:它们是在设计模式中用到的类。类可以在模式中扮演不同的角色,以完成多个目标。
- 非功能需求:诸如内存优化、可用性和性能等需求都属于此类型。由于这些因素影响整个软件解决方案,因此至关重要。
- 权衡:并非所有的设计模式都适合于应用程序开发,因此需要权衡。这些是在应用程序中使用设计模式时所做的决策。
- 结果:如果上下文不合适,设计模式可能对代码的其他部分产生负面影响。开发人员应该了解设计模式的结果和用途。
设计模式的分类
模式的分类主要基于对象的创建方式、软件应用程序中类和对象的构造方式,同时还涉及对象之间的交互方式。
创建型模式
- 它们的运行机制基于对象的创建方式
- 它们将对象的创建细节隔离开来
- 代码与所创建的对象的类型无关
单例模式是创建型模式的一个例子。
结构型模式
- 它们致力于设计出能够通过组合获得更强大功能的对象和类的结构。
- 重点是简化结构并识别类和对象之间的关系。
- 它们主要关注类的继承和组合。
适配器模式是结构型模式的一个例子。
行为型模式
- 它们关注对象之间的交互以及对象的响应性。
- 对象应该能够交互,同时仍然保持松散耦合。
观察者模式是行为型模式的一个例子。
网友评论