1、面向对象编程介绍

面向对象(object-oriented ;简称: OO) 至今还没有统一的概念 我这里把它定义为: 按人们 认识客观世界的系统思维方式,采用基于对象(实体) 的概念建立模型,模拟客观世界分析、设 计、实现软件的办法。

面向对象编程(Object Oriented Programming-OOP) 是一种解决软件复用的设计和编程方法。 这种方法把软件系统中相近相似的操作逻辑和操作 应用数据、状态,以类的型式描述出来,以对象实例的形式在软件系统中复用,以达到提高软件开发效率的作用。

面向对象的理解:
- 面向对象是一种设计思想
1. 符合人们的思考习惯
2. 把执行者变成指挥者
3. 简化功能,把复杂的事情简单化 - 想完成一个事,找具有这样功能的对象
- 如果能找到,调用这个对象的功能,完成这个事
- 如果找不到,创建具有这样功能的对象,再调用完成这个事
面向对象有三大特征:
1. 封装
2. 继承
3. 多态

2、类和对象

面向对象编程的2个非常重要的概念:类和对象

对象是面向对象编程的核心,在使用对象的过程中,为了将具有共同特征和行为的一组对象抽象定义,提出了另外一个新的概念——类

类就相当于制造飞机时的图纸,用它来进行创建的飞机就相当于对象

- 类是对事务的描述,是抽象的。
- 对象是类的具体体现。
- 类对事务的描述:属性(名词)和行为(动词)

2.1类

具有相同属性和行为事物的统称

2.2对象

某一个具体事物的存在 ,在现实世界中可以是看得见摸得着的

2.3类和对象之间的关系

小总结:类就是创建对象的模板

2.4类的构成

  • 类(Class) 由3个部分构成
  1. 类的名称:类名
  2. 类的属性:一组数据 属性、变量
  3. 类的方法:允许对进行操作的方法 (行为) 方法

2.5类的抽象

拥有相同(或者类似)属性和行为的对象都可以抽像出一个类

3、定义类

类是对事务的描述。
1、属性
2、行为 现在呢,要描述汽车这个类。
1、类名 Car 大驼峰命名法
2、属性
3、行为(语法与函数一样,这里叫方法) run stop
至少有一个参数,名字任意,一般都是self 对象是类的具体体现
创建对象 名字 = 类()
class Car:

	def run(self):
print('汽车奔跑中。。。。。。') def stop(self):
print('汽车急刹中。。。。。。') wlhgs = Car()
wlhgs.run()
wlhgs.stop() bcs = Car()
bm7 = Car()
ad8 = Car()
#每次创建都是新的对象
print(wlhgs,id(wlhgs))
print(bcs,id(bcs)) #虽然每个对象都有类里方法,但是其实是一个方法,地址一样。
print(id(wlhgs.run))
print(id(bcs.run))

4、创建对象

#创建类
class Car: def run(self):
print('汽车奔跑中。。。。。。') def stop(self):
print('汽车急刹中。。。。。。') def haha(self):
print('哈哈。。。。。。。') #创建对象-实例
bmw = Car()
#调用/执行实例方法
bmw.run()
#为对象实例设置一个属性
bmw.color = '黑色'
#获取对象实例的属性
print('颜色:%s'%(bmw.color))
bmw.brand = '宝马7系'
print('系列:%s'%(bmw.brand)) aodi = Car()
#此时aodi对象实例并没有color属性
#print(aodi.color)

5、__ init__()魔法方法

在上一小节的demo中,我们已经给BMW这个对象添加了2个属性,wheelNum(车的轮胎数量)以及color(车的颜色),试想如果再次创建一个对象的话,肯定也需要进行添加属性,显然这样做很费事,那么有没有办法能够在创建对象的时候,就顺便把车这个对象的属性给设置呢?

  • [x] 答:init()方法

5.1使用方法

在python中类似于这样格式__名字__()的方法叫做魔法方法

__init___
作用:
在对象创建的时候为对象添加属性--实例属性
特点:
在创建对象的时候,自动会被调用 self:当前对象实例,哪个对象调用了这个方法,self就是哪个对象

5.2__init__()方法的调用

class Car:
def __init__(self):
print('__init__......')
self.color = '黑色'
self.brand = '哈弗H6' def run(self):
print('汽车奔跑中。。。。。。%s,%s'%(self,id(self))) def stop(self):
print('汽车急刹中。。。。。。') #
#mumaren = Car()
#mumaren.run()
#print('%s,%s'%(mumaren,id(mumaren))) haval1 = Car()
print(haval1.color)
print(haval1.brand) haval2 = Car()
print(haval2.color)
print(haval2.brand)

5.3创建对象的时候同时初始化属性

class Car:
def __init__(self,color,brand):
print('__init__......')
self.color = color
self.brand = brand def run(self):
print('汽车奔跑中。。。。。。%s,%s'%(self,id(self))) def stop(self):
print('汽车急刹中。。。。。。') haval1 = Car('白色','哈弗h7')
print(haval1.color)
print(haval1.brand) haval2 = Car('银灰色','哈弗h9')
print(haval2.color)
print(haval2.brand) #对象是可变类型
haval3 = haval2
haval3.color = '黑色'
print(haval2.color)

5.4总结

  • 当创建Car对象后,在没有调用__init__()方法的前提下,BMW就默认拥有了2个属性wheelNum和color,原因是__init__()方法是在创建对象后,就立刻被默认调用了
  • init()方法,在创建一个对象时默认被调用,不需要手动调用
  • init(self)中,默认有1个参数名字为self,如果在创建对象时传递了2个实参,那么__init__(self)中除了self作为第一个形参外还需要2个形参,例如__init__(self,x,y)
  • init(self)中的self参数,不需要开发者传递,python解释器会自动把当前的对象引用传递进去

6、__ str__()魔法方法

5.1定义__str__()方法

__str__

什么时候调用? 对象转换成字符串   str(对象)  测试的时候,打印对象的信息

格式:
def __str__(self):
return 字符串 print打印的时候,默认就将内容转成字符串

6.2__str__()方法的调用

class Car:
def __init__(self,color,brand):
print('__init__......')
self.color = color
self.brand = brand def __str__(self):
print('__str__......')
return 'Car color:%s,brand:%s'%(self.color,self.brand) def run(self):
print('汽车奔跑中。。。。。。') def stop(self):
print('汽车急刹中。。。。。。') def show(self):
print('color:%s,brand:%s'%(self.color,self.brand)) haval1 = Car('白色','哈弗h7') print(haval1)
print(id(haval1))
#print(str(haval1))
#haval1.show()

6.3总结

  • 在python中方法名如果是__xxxx__()的,那么就有特殊的功能,因此叫做“魔法”方法
  • 当使用print输出对象的时候,只要自己定义了__str__(self)方法,那么就会打印从在这个方法中return的数据(如果__str__没有返回值,报错)

7、理解self

- self表示是当前对象,可以理解为自己
- 可以把self当做C++中类里面的this指针一样理解,就是对象自身的意思
- 某个对象调用其方法时,python解释器会把这个对象作为第一个参数传递给self,所以开发者只需要传递后面的参数即可

8、应用:烤地瓜

8.1分析’烤地瓜‘的属性和方法

示例属性如下:

  • cookedLevel : 这是数字;0~3表示还是生的,超过3表示半生不熟,超过5表示已经烤好了,超过8表示已经烤成木炭了!我们的地瓜开始时时生的
  • cookedString : 这是字符串;描述地瓜的生熟程度
  • condiments : 这是地瓜的配料列表,比如番茄酱、芥末酱等

示例方法如下:

  • cook(): 把地瓜烤一段时间
  • addCondiments(): 给地瓜添加配料
  • init(): 设置默认的属性
  • str(): 让print的结果看起来更好一些

8.2定义类,并且定义__init__()方法

#定义`地瓜`类
class SweetPotato:
'这是烤地瓜的类' #定义初始化方法
def __init__(self):
self.cookedLevel = 0
self.cookedString = "生的"
self.condiments = []

8.3添加’烤地瓜‘方法

    #烤地瓜方法
def cook(self, time):
self.cookedLevel += time
if self.cookedLevel > 8:
self.cookedString = "烤成灰了"
elif self.cookedLevel > 5:
self.cookedString = "烤好了"
elif self.cookedLevel > 3:
self.cookedString = "半生不熟"
else:
self.cookedString = "生的"

8.4基本功能已有,测试

  • 添加以下代码测试
mySweetPotato = SweetPotato()
print(mySweetPotato.cookedLevel)
print(mySweetPotato.cookedString)
print(mySweetPotato.condiments)

8.5测试cook方法是否好用

  • 在上面的代码最后面添加如下代码
print("------接下来要进行烤地瓜了-----")
mySweetPotato.cook(4) #烤4分钟
nt(mySweetPotato.cookedLevel)
print(mySweetPotato.cookedString)

运行结果为:

  • 0
  • 生的
  • []
  • ------接下来要进行烤地瓜了-----
  • 4
  • 半生不熟

8.6定义addCondiments()方法和__str__()方法

def __str__(self):
msg = self.cookedString + " 地瓜"
if len(self.condiments) > 0:
msg = msg + "("
for temp in self.condiments:
msg = msg + temp + ", "
msg = msg.strip(", ") msg = msg + ")"
return msg def addCondiments(self, condiments):
self.condiments.append(condiments)

8.7再次测试

定义类:
属性
1、cookedLevel int 0
2、cookedString str '生的'
3、condiments [] []
方法
1、初始化属性 __init__ cookedLevel,cookedString,condiments
2、烤地瓜 cook time
3、加调料 addCondiment condiment
4、地瓜的信息 __str__

完整的代码如下:

class SweetPotato:
"这是烤地瓜的类" #定义初始化方法
def __init__(self):
self.cookedLevel = 0
self.cookedString = "生的"
self.condiments = [] #定制print时的显示内容
def __str__(self):
msg = self.cookedString + " 地瓜"
if len(self.condiments) > 0:
msg = msg + "(" for temp in self.condiments:
msg = msg + temp + ", "
msg = msg.strip(", ") msg = msg + ")"
return msg #烤地瓜方法
def cook(self, time):
self.cookedLevel += time
if self.cookedLevel > 8:
self.cookedString = "烤成灰了"
elif self.cookedLevel > 5:
self.cookedString = "烤好了"
elif self.cookedLevel > 3:
self.cookedString = "半生不熟"
else:
self.cookedString = "生的" #添加配料
def addCondiments(self, condiments):
self.condiments.append(condiments) # 用来进行测试
mySweetPotato = SweetPotato()
print("------有了一个地瓜,还没有烤-----")
print(mySweetPotato.cookedLevel)
print(mySweetPotato.cookedString)
print(mySweetPotato.condiments)
print("------接下来要进行烤地瓜了-----")
print("------地瓜经烤了4分钟-----")
mySweetPotato.cook(4) #烤4分钟
print(mySweetPotato)
print("------地瓜又经烤了3分钟-----")
mySweetPotato.cook(3) #又烤了3分钟
print(mySweetPotato)
print("------接下来要添加配料-番茄酱------")
mySweetPotato.addCondiments("番茄酱")
print(mySweetPotato)
print("------地瓜又经烤了5分钟-----")
mySweetPotato.cook(5) #又烤了5分钟
print(mySweetPotato)
print("------接下来要添加配料-芥末酱------")
mySweetPotato.addCondiments("芥末酱")
print(mySweetPotato)

运行结果为:

  • ------有了一个地瓜,还没有烤-----
  • 0
  • 生的
  • []
  • ------接下来要进行烤地瓜了-----
  • ------地瓜经烤了4分钟-----
  • ------地瓜又经烤了3分钟-----
  • 半生不熟 地瓜
  • ------接下来要添加配料-番茄酱------
  • 烤好了 地瓜(番茄酱)
  • ------地瓜又经烤了5分钟-----
  • 烤成灰了 地瓜(番茄酱)
  • ------接下来要添加配料-芥末酱------
  • 烤成灰了 地瓜(番茄酱,芥末酱)

9、应用:存放家具

home类:
属性
1、面积
方法
2、存放家具 bed类:
属性:
1、面积
2、名字
#定义一个home类
class Home: def __init__(self, area):
self.area = area #房间剩余的可用面积
#self.light = 'on' #灯默认是亮的
self.containsItem = [] def __str__(self):
msg = "当前房间可用面积为:" + str(self.area)
if len(self.containsItem) > 0:
msg = msg + " 容纳的物品有: "
for temp in self.containsItem:
msg = msg + temp.getName() + ", "
msg = msg.strip(", ")
return msg #容纳物品
def accommodateItem(self,item):
#如果可用面积大于物品的占用面积
needArea = item.getUsedArea()
if self.area > needArea:
self.containsItem.append(item)
self.area -= needArea
print("ok:已经存放到房间中")
else:
print("err:房间可用面积为:%d,但是当前要存放的物品需要的面积为%d"%(self.area, needArea)) #定义bed类
class Bed: def __init__(self,area,name = '床'):
self.name = name
self.area = area def __str__(self):
msg = '床的面积为:' + str(self.area)
return msg #获取床的占用面积
def getUsedArea(self):
return self.area def getName(self):
return self.name #创建一个新家对象
newHome = Home(100)#100平米
print(newHome) #创建一个床对象
newBed = Bed(20)
print(newBed) #把床安放到家里
newHome.accommodateItem(newBed)
print(newHome) #创建一个床对象
newBed2 = Bed(30,'席梦思')
print(newBed2) #把床安放到家里
newHome.accommodateItem(newBed2)
print(newHome)
  • 如果一个对象与另外一个对象有一定的关系,那么一个对象可用是另外一个对象的属性

10、保护对象的属性(私有属性)

如果有一个对象,当需要对其进行修改属性时,有2种方法

对象名.属性名 = 数据 ---->直接修改

对象名.方法名() ---->间接修改

为了更好的保存属性安全,即不能随意修改,一般的处理方式为

将属性定义为私有属性
添加一个可以调用的方法,供调用

私有化某些敏感的数据属性,

对外提供可访问的接口(方法),

这也是一种封装

在java,C#中,要求:

1、所有的属性私有化
2、对外提供get,set

python没要求。

如果某些属性就是不让外部访问,直接__属性名 私有化
是否提供对外访问的接口,根据需要。
class Person:

	def __init__(self):
self.__age = 18 def getAge(self):
#判断一些业务逻辑,如果符号要去,给你数据,不符合,不给。
return self.__age; def setAge(self,age):
if age<0 or age>120:
print('年龄不符合要求。。。。。。')
else:
self.__age = age laowang = Person()
print(laowang.getAge())
laowang.setAge(-40)
print(laowang.getAge())

11、__ del__()魔法方法(了解即可)

创建对象后,python解释器默认调用__init__()方法;

当删除一个对象时,python解释器也会默认调用一个方法,这个方法为__del__()方法

import time

class Animal:
# 初始化方法
# 创建完对象后会自动被调用
def __init__(self, name):
print('__init__方法被调用')
self.__name = name #对象在被垃圾回收机制的时候调用这个方法,来释放资源。除非有特殊要求,一般不要重写。
#在关闭数据库连接对象的时候,可以在这里,释放资源
def __del__(self):
print('__del__......') wangcai = Animal('旺财')
xiaoqiang = wangcai del wangcai
print('*'*50)
del xiaoqiang time.sleep(10) print('over......')

12、继承介绍以及单继承

将共性的内容放在父类中,子类只需要关注自己特有的内容

python中所有的内容都是对象,所有的对象都直接或间接继承了object

12.1继承的概念

在程序中,继承描述的是事物之间的所属关系,例如猫和狗都属于动物,程序中便可以描述为猫和狗继承自动物

12.2单继承

将共性的内容放在父类中

子类只关注自己特有的内容

扩展性高,代码更简洁

# 定义一个父类
class Dog(object):
def __init__(self,name,color):
self.name = name
self.color = color def run(self):
print('%s %s run......'%(self.name,self.color))
# 定义一个子类,继承Dog类
class TaiDi(Dog):
def setName(self,name):
self.name = name taidi = TaiDi('泰迪','棕色')
taidi.run() #泰迪 棕色 run...... taidi.setName('泰迪弟')
taidi.run() #泰迪弟 棕色 run......

总结

  • 子类在继承的时候,在定义类时,小括号()中为父类的名字
  • 父类的属性、方法,会被继承给子类

12.3私有的不能被继承

class Animal(object):

    def __init__(self, name='动物', color='白色'):
self.__name = name
self.color = color def __test(self):
print(self.__name)
print(self.color) def test(self):
print(self.__name)
print(self.color) class Dog(Animal):
def dogTest1(self):
#print(self.__name) #不能访问到父类的私有属性
print(self.color) def dogTest2(self):
#self.__test() #不能访问父类中的私有方法
self.test() A = Animal()
#print(A.__name) #程序出现异常,不能访问私有属性
print(A.color)
#A.__test() #程序出现异常,不能访问私有方法
A.test() print("------分割线-----") D = Dog(name = "小花狗", color = "黄色")
D.dogTest1()
D.dogTest2()

总结

  • 私有的属性,不能通过对象直接访问,但是可以通过方法访问
  • 私有的方法,不能通过对象直接访问
  • 私有的属性、方法,不会被子类继承,也不能被访问
  • 一般情况下,私有的属性、方法都是不对外公布的,往往用来做内部的事情,起到安全的作用

13、多继承

多继承:这个类继承了多个父类,是有顺序

继承具有传递性

继承之后,此对象的方法或属性就增加。
调用的时候,注意是否自己有,或者父类有。
class A(object):
def a(self):
print('a......') class B:
def b(self):
self.c() #这里又调用C()中的c
print('b......') class C(A,B):
def c(self):
print('c......') #
#laowang = C()
#laowang.a()
#laowang.b()
#laowang.c() x = C()
x.b() #c......
#b...... #获取父类
print(C.__bases__) #(<class '__main__.A'>, <class '__main__.B'>)
print(A.__bases__) #(<class 'object'>,) #列举,这个类和继承类的结构。调用方法的顺序**(类名.__mro__)**
print(C.__mro__) #(<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>)

14、重写

14.1重写父类方法

所谓重写,就是子类中,有一个和父类相同名字的方法,在子类中的方法会覆盖掉父类中同名的方法

class A(object):
def haha(self):
print('haha a......') class B(A):
def haha(self):
print('哈哈 b......') b = B()
b.haha()

14.2调用父类的方法

  • 子类覆盖父类,有两种方法可以调用父类的方法
class C2:
def haha(self):
print('haha 2......') class C3:
def haha(self):
print('haha 3......') class C4(C3,C2):
def haha(self):
#super().haha()
C2.haha(self)
print('haha 4......') laowang= C4()
laowang.haha()
print(C4.__mro__)
class Fu:
def __init__(self,name,age):
print('fu...%s'%(id(self)))
self.name = name
self.age = age class Zi(Fu):
def __init__(self,name,age,sex):
print('zi...%s'%(id(self)))
#super().__init__(name,age) #这是方法一
Fu.__init__(self,name,age) #这是方法二
self.sex = sex def show(self):
print('%s,%s,%s'%(self.name,self.age,self.sex)) zi = Zi('老王',43,'男')
zi.show()
print(id(zi))

15、多态

  • 所谓多态:定义时的类型和运行时的类型不一样,此时就成为多态

多态的概念是应用于Java和C#这一类强类型语言中,而Python崇尚“鸭子类型”。

首先Python不支持多态,也不用支持多态,python是一种多态语言,崇尚鸭子类型。

在程序设计中,鸭子类型(英语:duck typing)是动态类型的一种风格。在这种风格中,一个对象有效的语义,不是由继承自特定的类或实现特定的接口,而是由当前方法和属性的集合决定。

python既可以说支持多态,也可以说不支持多态

	1、支持多态
python的弱类型,变量的类型是根据赋值的类型判断的,值是什么类型,变量就是什么类型
这就是多态 2、不支持多态
因为python是弱类型语言,没有要求类型,不完全符合多态的定义。
class F1(object):
def show(self):
print('F1.show') class S1(F1):
def show(self):
print('S1.show') class S2(F1):
def show(self):
print('S2.show') def func(obj):
obj.show()
#print(type(obj)) s1_obj = S1()
func(s1_obj) s2_obj = S2()
func(s2_obj) f1 = F1()
func(f1)

16、类属性、实例属性

  • 直接在类中定义的,与方法平齐,不在方法里的属性就是 类属性
  • 在方法里通过self.属性 都是实例属性

16.1类属性

class People(object):
name = 'Tom' #公有的类属性
__age = 12 #私有的类属性 p = People() print(p.name) #正确
print(People.name) #正确
print(p.__age) #错误,不能在类外通过实例对象访问私有的类属性
print(People.__age) #错误,不能在类外通过类对象访问私有的类属性

16.2实例属性(对象属性)

class People(object):
address = '山东' #类属性
def __init__(self):
self.name = 'xiaowang' #实例属性
self.age = 20 #实例属性 p = People()
p.age =12 #实例属性
print(p.address) #正确
print(p.name) #正确
print(p.age) #正确 print(People.address) #正确
print(People.name) #错误
print(People.age) #错误

16.3通过实例(对象)去修改类属性

class People(object):
country = 'china' #类属性 print(People.country)
p = People()
print(p.country)
p.country = 'japan'
print(p.country) #实例属性会屏蔽掉同名的类属性
print(People.country)
del p.country #删除实例属性
print(p.country)

总结

  • 如果需要在类外修改类属性,必须通过类对象去引用然后进行修改。如果通过实例对象去引用,会产生一个同名的实例属性,这种方式修改的是实例属性,不会影响到类属性,并且之后如果通过实例对象去引用该名称的属性,实例属性会强制屏蔽掉类属性,即引用的是实例属性,除非删除了该实例属性。

17、实例方法、类方法和静态方法

17.1实例方法

实例方法/对象方法,有一个参数,一般叫self
在使用的时候,对象.方法名(实参)
self不需要手动传值,默认将当前对象传递过去给self

17.2类方法

语法:

@classmethod
def 方法名(cls,x,y,z...):
语句 调用:
对象名.
类名. cls:类对象 类也是对象,type的对象, 在类方法中,设置的属性,是类属性,所有对象共享。 什么时候用类方法呢?
1、想通过类直接访问的方法
2、想通过方法来设置或者修改类属性
class People(object):
country = 'china' #类方法,用classmethod来进行修饰
@classmethod
def getCountry(cls):
return cls.country @classmethod
def setCountry(cls,country):
cls.country = country p = People() print(p.getCountry()) #china #可以用过实例对象引用
print(People.getCountry())#china #可以通过类对象引用 p.setCountry('japan') print(p.getCountry()) #japan

17.3静态方法

语法:
@staticmethod
def 名(形参):
语句 实例方法必须至少有一个参数放在第一个,一般叫self
类方法必须至少有一个参数放在第一个,一般叫cls 静态方法可以没有参数,也可以有参数,但是无法直接获取类对象和实例对象
所以一般静态方法里的功能,不与对象相关
class Dog:
age = 18 def __init__(self,name):
self.name = name @staticmethod
def show():
print('show.....%s'%(Dog.age)) d = Dog('旺财')
d.show() #show.....18 - 静态方法中不需要额外定义参数
- 因此在静态方法中引用类属性的话,必须通过类对象来引用

18、设计模式

18.1设计模式的六大原则

  1. 设计模式六大原则(1):单一职责原则

    即一个类只负责一项职责

  2. 设计模式六大原则(2):里氏替换原则

    所有引用基类的地方必须能透明地使用其子类的对象

  3. 设计模式六大原则(3):依赖倒置原则

    高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象。

  4. 设计模式六大原则(4):接口隔离原则

    客户端不应该依赖它不需要的接口;一个类对另一个类的依赖应该建立在最小的接口上。

  5. 设计模式六大原则(5):迪米特法则

    一个对象应该对其他对象保持最少的了解。尽量降低类与类之间的耦合。

  6. 设计模式六大原则(6):开闭原则

    一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。

18.2分类

1.创建型模式

主要目的:创建对象

共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。

2.结构型模式

主要目的:对象的组成和对象的关系

共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。

3.行为型模式

主要目的:对象的行为,对象能做什么

共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

19、工厂设计模式

组成:

  1. 工厂类角色:这是本模式的核心,含有一定的商业逻辑和判断逻辑,用来创建产品
  2. 抽象产品角色:它一般是具体产品继承的父类或者实现的接口。
  3. 具体产品角色:工厂类所创建的对象就是此角色的实例。

19.1简单工厂模式

实例:

'''
抽象角色(父类):它一般是具体产品继承的父类或者实现的接口
'''
class Car(object):
def move(self):
pass
def stop(self):
pass '''
具体产品角色(继承抽象角色):工厂类所创建的对象就是此角色的实例。
'''
class H1(Car):
def move(self):
print('哈弗h1 move......') def stop(self):
print('哈弗h1 stop......') class H9(Car):
def move(self):
print('哈弗h9 move......') def stop(self):
print('哈弗h9 stop......') class H7(Car):
def move(self):
print('哈弗h7 move......') def stop(self):
print('哈弗h7 stop......') class H6(Car):
def move(self):
print('哈弗h6 move......') def stop(self):
print('哈弗h6 stop......') '''
工厂类角色:这是本模式的核心,含有一定的逻辑判断,用来创建产品
'''
class CarFactory:
@classmethod
def createCar(cls,name):
car = None
if name=='哈弗H1':
car = H1()
elif name=='哈弗H9':
car = H9()
elif name=='哈弗H7':
car = H7()
elif name=='哈弗H6':
car = H6()
return car '''
主代码
'''
name = input('请输入要购买的车型:')
car = CarFactory.createCar(name)
if car!=None:
car.move()
car.stop()
else:
print('没有。。。。。。。')

说明:

工厂函数、工厂类对具体的生成环节进行了封装,这样有利于代码的后需扩展,即把功能划分的更具体,4s店只负责销售,汽车厂只负责制造

总结:

对象创建比较复杂的时候,可以考虑使用简单工厂

  1. 优点:

    在简单工厂中主函数或者客户端不再负责对象的创建,而是把这个责任交给工厂类,主函数或者客户端在使用对象的时候只从工厂中调用就行了,从而明确了各个类的职责,符合单一职责原则)
  2. 缺点:

    由于这个工厂类负责所有对象的创建,那么当子类增多时,我们就需要去修改工厂类的代码,这样呢,就违反了一个原则:开闭原则

19.2工厂方法模式

'''
抽象角色(父类):它一般是具体产品继承的父类或者实现的接口
'''
class Car(object):
def move(self):
pass
def stop(self):
pass '''
具体产品角色(继承抽象角色):工厂类所创建的对象就是此角色的实例。
'''
class H1(Car):
def move(self):
print('哈弗h1 move......') def stop(self):
print('哈弗h1 stop......') class H9(Car):
def move(self):
print('哈弗h9 move......') def stop(self):
print('哈弗h9 stop......') class H7(Car):
def move(self):
print('哈弗h7 move......') def stop(self):
print('哈弗h7 stop......') '''
抽象工厂类角色
''' class CarFactory:
@classmethod
def createCar(cls,name):
pass '''
具体工厂类角色:这是本模式的核心,含有一定的逻辑判断,用来创建产品
'''
class H1Factory(CarFactory):
@classmethod
def createCar(cls,name):
return H1() class H9Factory(CarFactory):
@classmethod
def createCar(cls,name):
return H9() class H7Factory(CarFactory):
@classmethod
def createCar(cls,name):
return H7()
'''
主代码
'''
name = input('请输入要购买的车型:')
car = None if name=='哈弗H1':
car = H1Factory.createCar(name)
elif name=='哈弗H9':
car = H9Factory.createCar(name) if car!=None:
car.move()
car.stop()
else:
print('没有。。。。。。。')

总结:

工厂方法模式的优点和缺点

  1. 优点:

    解决了简单工厂模式的违反开闭原则
  2. 缺点:

    1如果需要增加一个具体产品类角色,需要添加这个类和对应的工厂类。代码量大。

20、__new__魔法方法的使用

a1 = A()

创建对象的步骤
1、首先调用__new__得到一个对象
2、调用__init__为对象添加属性
3、将对象赋值给变量
class A(object):
def __init__(self):
print("这是 init 方法") def __new__(cls):
print(id(cls))
print("这是 new 方法")
return object.__new__(cls) a1 = A()
print(a1)
#7214424
#这是 new 方法
#这是 init 方法
#<__main__.A object at 0x0000000000BDEB00>
print(id(a1)) #12446464
print(id(A)) #7214424

总结

  • __new__至少要有一个参数cls,代表要实例化的类,此参数在实例化时由Python解释器自动提供
  • __new__必须要有返回值,返回实例化出来的实例,这点在自己实现__new__时要特别注意,可以return父类__new__出来的实例,或者直接是object的__new__出来的实例
  • __init__有一个参数self,就是这个__new__返回的实例,__init__在__new__的基础上可以完成一些其它初始化的动作,__init__不需要返回值
  • 我们可以将类比作制造商,__new__方法就是前期的原材料购买环节,__init__方法就是在有原材料的基础上,加工,初始化商品环节

21、单例设计模式(单列模式Singleton)

21.1单例是什么

确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类,单例模式是一种对象创建型模式。

21.2创建单例-保证只有1个对象

1、单例模式Singleton
在项目中某些对象,只有一个,可以一直使用。
如果再次实例化,会很占资源和时间。
所以,这样的对象就需要设计成单例模式。 2、原型模式Prototype
可以实例化多个对象,每个都是新的,以前设计的类都是原型模式 object.__new__(cls):
表示创建了一个实例对象
class Singleton:
#表示对象是否被创建 None:没有,其它:已经创建
__instance = None
def __new__(cls):
if cls.__instance == None:
cls.__instance = object.__new__(cls) return cls.__instance s1 = Singleton()
s2 = Singleton()
s3 = Singleton()
print(id(s1)) #18342968
print(id(s2)) #18342968
print(id(s3)) #18342968

21.3不定长参数

class Singleton:
#表示对象是否被创建 None:没有,其它:已经创建
__instance = None
#表示是不是第一次调用init: True:第一次调用 False:不是第一次调用
__firstInit = True
def __init__(self,*args,**kwargs):
if Singleton.__firstInit:
self.args = args
self.kwargs = kwargs
Singleton.__firstInit=False
def __new__(cls,*args,**kwargs):
if cls.__instance == None:
cls.__instance = object.__new__(cls) return cls.__instance s1 = Singleton('老王',10,'add','',money=12345)
print(id(s1)) #8514472
print(s1.args[0]) #老王
print(s1.args[2]) #add
print(s1.kwargs['money'])#12345 s2 = Singleton('旺财')
print(id(s2)) #8514472
print(s2.args[0]) #老王
print(s2.args[2]) #add
print(s2.kwargs['money'])#12345 s3 = Singleton()
print(s3.kwargs['money'])#12345

02.OOP面向对象-1.面向对象介绍的更多相关文章

  1. Day7 初识面向对象,面向对象之继承、多态和封装

    一.面向对象引言 一.面向对象的程序设计的由来 详述见:http://www.cnblogs.com/linhaifeng/articles/6428835.html 二.面向对象引子 写一个简单程序 ...

  2. Python面向对象学习 1 (什么是面向对象,面向对象的应用场景,待更新)

    程序设计的三种基本结构: 面向对象,面向过程,函数式编程   1,什么是面向对象编程    面向对象编程是一种编程方式,此编程方式的落地需要使用 “类” 和 “对象” 来实现,所以,面向对象编程其实就 ...

  3. PHP之面向对象PHP之面向对象(面向对象是什么)

    PHP之面向对象(面向对象是什么) 一.总结 一句话总结: 面向对象就是类:类都要 属性 和 方法 比如人:属性比如身高体重,方法比如吃饭喝水 面向对象中 ,方法即是函数 : 属性即是变量 ,只是面相 ...

  4. 什么是php面向对象及面向对象的三大特性

    什么是面向对象? 面向对象编程,也就是我们常说的OOP,其实是面向对象的一部分.面向对象一共有3个部分:面向对象分析(OOA).面向对象设计(OOD).面向对象编程(OOP).我们现在将要学习的就是面 ...

  5. C#基础知识之面向对象以及面向对象的三大特性

    在C#基础知识之类和结构体中我详细记录了类.类成员.重载.重写.继承等知识总结.这里就记录一下对面向对象和面向对象三大特性的广义理解. 一.理解面向对象 类是面向对象编程的基本单元,面向对象思想其实就 ...

  6. Python之面向对象:面向对象基础

    一.面向过程.面向对象对比 1.面向过程 根据业务逻辑从上到下写垒代码 2.函数式思想 将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可 3.面向对象 对函数进行分类和封装 1.2.3一步 ...

  7. Python面向对象01 /面向对象初识、面向对象结构、类、self、实例化对象

    Python面向对象01 /面向对象初识.面向对象结构.类.self.实例化对象 目录 Python面向对象01 /面向对象初识.面向对象结构.类.self.实例化对象 1. 面向对象初识 2. 面向 ...

  8. 02.OOP面向对象-3.一些理解

    对封装的理解? 封装,类本身就是一个封装,封装了属性和方法.方法也是封装,对一些业务逻辑的封装.私有也是封装,将一些方法和属性私有化,对外提供可访问的接口. 对继承的理解 将共性的内容放在父类中,子类 ...

  9. 02.OOP面向对象-2.例子

    class clothes: #初始化属性 def __init__(self,name,color): self.name = name self.color = color #转字符串 def _ ...

随机推荐

  1. HDU 4518

    整理一下思路,明天再写... 这道题,其实就是求包含大于10的斐波那切数字的第K(K是斐波那契数)个数.注意到斐波那契数的爆炸性增长,所以在范围 内的符合要求的F数并不多吧.比如求第K个F数,那么,前 ...

  2. wifi断线问题

    近期在项目中,遇到wifi常常断线现象,平台是Android平台,现象是:连接wifi后,长时间播放视频,会出现wifi断开,界面上WiFi图标显示打叉,请问有WiFi方面的行家朋友,有没有办法来检測 ...

  3. [Linux]RedHat Linux 忘记rootpassword该怎样又一次设置password

    1. 开机在出现grub画面,按e键,例如以下图所看到的: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvU3VubnlZb29uYQ==/font/5a6 ...

  4. oc10--练习

    // // main.m // 练习 #import <Foundation/Foundation.h> @interface Car : NSObject { @public int w ...

  5. Node.js:工具模块

    ylbtech-Node.js:工具模块 1.返回顶部 1. Node.js 工具模块 在 Node.js 模块库中有很多好用的模块.接下来我们为大家介绍几种常用模块的使用: 序号 模块名 & ...

  6. consul 集群安装

    上图是官网提供的一个事例系统图,图中的Server是consul服务端高可用集群,Client是consul客户端.consul客户端不保存数据,客户端将接收到的请求转发给响应的Server端.Ser ...

  7. redis集群部署及常用的操作命令_01

    简单说下自己测试搭建简单的redis集群的大体步骤: 1.首先你的有6个redis(官方说最少6个,3master,3slave),可以先在一台机器上搭建,搭建到多台上应该只需要改变启动命令即可(可能 ...

  8. 使用 `ConfigMap` 挂载配置文件

    使用 ConfigMap 挂载配置文件 Intro 有一些敏感信息比如数据库连接字符串之类的出于安全考虑,这些敏感信息保存在了 Azure KeyVault 中,最近应用上了 k8s 部署,所以想把 ...

  9. Solr.NET快速入门(四)【相似查询,拼写检查】

    相似查询 此功能会返回原始查询结果中返回的每个文档的类似文档列表. 参数通过QueryOptions的MoreLikeThis属性定义. 示例:搜索"apache",为结果中的每个 ...

  10. html中DTD使用小结

    DTD 是一套关于标记符的语法规则.它是XML1.0版规格得一部分,是html文件的验证机制,属于html文件组成的一部分. DTD:三种文档类型:S(Strict).T(Transitional). ...