设计模式与面向对象

一、设计模式

  设计模式:对软件设计中普遍存在(反复出现)的各种问题,所提出的解决方案。

  每一个设计模式系统地命名、解释和评价了面向对象系统中一个重要的和重复出现的设计

  设计模式的创始人,一般称为“四人帮”(Gang of Four, GoF):Erich Gamma,Richard Helm,Ralph Johnson,John Vlissides......他们编写一套书来介绍23种设计模式:《设计模式:可复用面向对象软件的基础》。

二、面向对象回顾

  设计模式是用来设计面向对象系统中的设计。不解决面向过程的问题。

1、面向对象的三大特性

  封装:把数据和函数封装到一个类里,体现类内和类外。

  继承:由于有了封装,需要通过继承在类之间复用代码。

  多态:python本身是一门多态语言,因此不需去处理多态的问题。Java中则会区分虚类和普通类。

  因此这三个特性是一个递进的关系。

2、接口

  接口:若干抽象方法的集合。

  作用:限制实现接口类必须按照接口给定的调用方式实现这些方法;对高层模块隐藏了类的内部实现

# 方法一:继承
# 存在的问题是:如果不调用pay方法并不会报错
class Payment:
    def pay(self, money):
        raise NotImplementedError

class Alipay(Payment):
    pass

class WechatPay(Payment):
    pass

p = Alipay()
p.pay(100)


# 方法二:抽象类
# 约束子类必须实现抽象类:TypeError: Can't instantiate abstract class Alipay with abstract methods pay
from abc import ABCMeta, abstractmethod

class Payment(metaclass=ABCMeta):
    # abstract class
    @abstractmethod
    def pay(self, money):   # 抽象方法
        pass

class Alipay(Payment):
    def pay(self, money):   # 实现Payment接口
        print('支付宝支付%d元' % money)

class WechatPay(Payment):
    def pay(self, money):   # 实现Payment接口
        print("微信支付%d元" % money)

p = Alipay()
p.pay(100)

  不用去查看具体实现,只要去查看接口(抽象类)的结构和注释,就可以了解需要传递的参数和pay方法的使用。

  在写底层模块或者开源框架时需要大量应用设计模式,优化封装,让程序员在学习和使用时非常方便。

三、面向对象设计SOLID原则

  不管是面向对象设计还是各个设计模式都需要遵循这五大原则。

  • 开放封闭原则:一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。即软件实体应尽量在不修改原有代码的情况下进行扩展
  • 里氏替换原则:所有引用父类的地方必须能透明地使用其子类的对象。(子类是特殊的父类,子类继承父类时同样方法的表现一致)
    # 子类和父类的show_name内部实现和逻辑可能不同,但是参数和返回值是相同的
    class User:
        def show_name(self):
            pass
    
    class VIPUser(User):
        def show_name(self):
            pass
    
    def show_user(u):  # u可以是普通用户或VIP
        res = u.show_name()
  • 依赖倒置原则:高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象。换言之,要针对接口编程,而不是针对实现编程。
    from abc import ABCMeta, abstractmethod
    
    class Payment(metaclass=ABCMeta):  # 抽象
        # abstract class
        @abstractmethod
        def pay(self, money):   # 抽象方法
            pass
    
    class Alipay(Payment):      # 细节
        def pay(self, money):   # 实现Payment接口
            print('支付宝支付%d元' % money)
    
    class WechatPay(Payment):   # 细节
        def pay(self, money):   # 实现Payment接口
            print("微信支付%d元" % money)
  • 接口隔离原则:使用多个专门的接口,而不使用单一的总接口,即客户端不应该依赖那些它不需要的接口。
    from abc import ABCMeta, abstractmethod
    
    # (一)单一总接口的情况
    # 子类必须实现所有抽象方法,但其实很多方法是子类不需要的
    class Animal(metaclass=ABCMeta):
        @abstractmethod
        def walk(self):
            pass
    
        @abstractmethod
        def swim(self):
            pass
    
        @abstractmethod
        def fly(self):
            pass
    
    class Tiger(Animal): # Class Tiger must implement all abstract methods
        def walk(self):
            print("老虎走路")
    
    # (二)多个接口隔离情况
    class LandAnimal(metaclass=ABCMeta):
        @abstractmethod
        def walk(self):
            pass
    
    class WaterAnimal(metaclass=ABCMeta):
        @abstractmethod
        def swim(self):
            pass
    
    class SkyAnimal(metaclass=ABCMeta):
        @abstractmethod
        def fly(self):
            pass
    
    class Tiger(LandAnimal):
        def walk(self):
            print("老虎走路")
    
    class Frag(LandAnimal,WaterAnimal):  # 青蛙多继承
        pass
  • 单一职责原则:不要存在多于一个导致类变更的原因。通俗的说,即一个类只负责一项职责

四、设计模式分类

1、创建型模式(5种)

  主要聚焦怎么去创建对象。目的是为了隐藏底层模块的逻辑。

  工厂方法模式、抽象工厂模式、创建者模式、原型模式、单例模式。

  创建型模式

2、结构型模式(7种)

  主要关注在几个类之间怎么组合协同工作在一起。

  适配器模式、桥模式、组合模式、装饰模式、外观模式、享元模式、代理模式。

  结构型模式

3、行为型模式(11种)

  主要关注方法和行为的完成。

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

  行为型模式

五、设计模式总结

  python这门语言是一个动态语言,对参数、父类子类等限制不严格。对设计模式并不强求,不是完全契合,而java则是完全与设计模式契合。但是了解一些设计模式对写出优秀代码还是非常有帮助的。

  在写大型项目时,尤其是底层代码、开源框架等时,设计模式的优势将更加突出。

 

posted @ 2019-02-14 13:33  休耕  阅读(1569)  评论(0编辑  收藏  举报