# 设计模式:
《设计模式》
接口类:Python原生不支持;
抽象类:Python原生支持的。
例:
from abc import abstractmethod, ABCMeta
class Payment(metaclass=ABCMeta): # 元类 默认的元类是 type 规范类
@abstractmethod
def pay(self, money):
raise NotImplemented # 没有实现方法
class WeChat(Payment):
def pay(self, money):
print("已经使用微信成功支持了%s 元" % money)
class AliPay(Payment):
def pay(self, money):
print("已经使用AliPay成功支付了%s 元" % money)
class ApplePay(Payment):
def pay(self, money):
print("已经使用ApplePay成功支付了%s 元" % money)
def pay(pay_obj, money): # 统一支付入口
pay_obj.pay(money)
# wechat = WeChat()
# wechat.pay()
#
# ali = AliPay()
# ali.pay()
app = ApplePay()
# pay(wechat, 100)
# pay(ali, 100)
pay(app, 100)
接口类,默认是多继承,接口类中的所有方法都必须不能实现——java。
抽象类, 不支持多继承,使用单继承。抽象类中的方法可以有一些代码的实现。——java。
规范子类。
实践中,继承的第一种含义意义并不是很大,甚至常常是有害的,因为它使得子类与基类出现强耦合。
继承的第二种含义非常重要。它又叫“接口继承”。
接口继承实质上是要求“做一个良好的抽象,这个抽象规定了一个兼容接口,使得外部调用者无需关心具体细节,可一视同仁地处理实现了特定接口的所有对象”, 这在程序设计上,叫做归一化。
归一化使得高层的外部使用者可以不加区分的处理所有接口兼容的对象集合。就好像Linux的泛文件概念一样,所有的东西都可以当文件处理,不必关心它是内存、磁盘、网络还是屏幕。(当然对底层设计者,当然可以区分出“字符设备”和“块设备”,然后做出针对性的设计,细致到什么程度,视需求而定。)
依赖倒置原则: 高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该应该依赖细节;细节应该依赖抽象。换言之,要针对接口编程,而不是针对实现编程
在Python中根本没有一个叫做interface的关键字,上面的代码只是看起来像接口,其实并没有起到接口的作用,子类完全可以不用去实现接口,如果非要去仿真接口的概念,可以借助第三方模块:
抽象类:
Python也有抽象类的概念但同样需要借助模块来实现,抽象类是一个特殊的类,它的特殊之处在于只能被继承,不能被实例化。
为什么要有抽象类?
如果说类是从一堆对象中抽取相同的内容而来的,那么抽象类是从一堆类中抽取相同的内容而来的,内容包括数据属性和函数属性。
水果是一个抽象类,吃水果,是吃的一个具体的桃子、一个具体的香蕉……我们永远无法吃到一个叫做水果的东西。
从设计角度来看,如果类是从现实对象抽象而来的,那么抽象类是基于类抽象而来的。
从实现角度来看,抽象类与普通类的不同之处:抽象类中有抽象方法,该类不能被实例化,只能被继承,且子类必须实现抽象方法。这一点与接口有点类似。
#一切皆文件
import abc # 利用abc模块实现抽象类
class All_file(metaclass=abc.ABCMeta):
all_type='file'
@abc.abstractmethod # 定义抽象方法,无需实现功能
def read(self):
'子类必须定义读功能'
pass
@abc.abstractmethod # 定义抽象方法,无需实现功能
def write(self):
'子类必须定义写功能'
pass
# class Txt(All_file):
# pass
#
# t1=Txt() #报错,子类没有定义抽象方法
class Txt(All_file): #子类继承抽象类,但是必须定义read和write方法
def read(self):
print('文本数据的读取方法')
def write(self):
print('文本数据的读取方法')
class Sata(All_file): #子类继承抽象类,但是必须定义read和write方法
def read(self):
print('硬盘数据的读取方法')
def write(self):
print('硬盘数据的读取方法')
class Process(All_file): #子类继承抽象类,但是必须定义read和write方法
def read(self):
print('进程数据的读取方法')
def write(self):
print('进程数据的读取方法')
wenbenwenjian=Txt()
yingpanwenjian=Sata()
jinchengwenjian=Process()
#这样大家都是被归一化了,也就是一切皆文件的思想
wenbenwenjian.read()
yingpanwenjian.write()
jinchengwenjian.read()
print(wenbenwenjian.all_type)
print(yingpanwenjian.all_type)
print(jinchengwenjian.all_type)
抽象类和接口类:
抽象类的本质还是类,指的是一组类的相似性,包括数据属性和函数属性。
而接口只强调函数属性的相似性。
抽象类是一个介于类和接口之间的一个概念。同时具备类和接口的部分特性,可以用来实现归一化设计。