17-面向对象之语法(2)

10. 设计模式:

1. _new_()的作用:

  • 真正构造一个instance并return,如果不return,那么就没有instance

  • 系统默认隐式地调用这两个魔术方法,当然,自己也可以重写,以及显式调用

    class Animal(object):
    def init():
    print("我是Animal的init,没有得到instance ")
    def new(cls): #因为没有return 一个instance,所以上面的init就不会被调用
    print("我是Animal的new,没有创造instance,也没有return出去instance ")
    a = Animal()
    print(' ')

    class Temp(object):
    def init(self):
    print("我是Temp的init ")
    def new(cls):
    print("我是Temp的new ")
    return super().new(cls) #调用父类的new,构造一个对象

    class People(object):
    def init(self): #当前这个self默认接收了new方法return的instance,并对这个instance做init
    print("我是People的init ")
    def new(cls):
    print("我是People的new,我创造了一个instance并return出去了 ")
    instance = super().new(cls) #调用父类的new,构造一个对象, 隶属于People
    #instance = Temp() #调用其他类产生一个instance,隶属于Temp,但没法调用people的init;

          return instance                 #把这个instance返回出去
    

    p = People()
    print(p,' ')

2. 单例模式

某个class创建实例的开销极大,而且一个对象足够使用,就用单例模式

  • 实现一:通过调用类方法返回一个instance,每次想得到一个新的instance都这样操作

    class User(object):
    __instance=None

      def __init__(self,name):
          self.name=name
          
      @classmethod #类方法
      def get_instance(cls,name): #由上面的init说明这里要构造一个形参为name
          if not cls.__instance:  #如果__instance 为None
              cls.__instance = User(name) #之后就去__init__()把当前这个instance的name设置好
          return cls.__instance #确保只构造了一个instance,并且这个instance的name已经设置好
    

    u1 = User.get_instance("zs") #调用类方法来获得instance,而不是一般的new一个instance
    u2 = User.get_instance("ls")

    u3=User("ww")

    print(u1==u2)

    ==判断表达式如果返回True,这两个对象是一个对象,并且内存地址相同

    print(u1.name, u2.name) #分析代码过程,打印的是'zs'

    print("u1对象的内存地址:%s,u2对象的内存地址:%s"%(id(u1),id(u2)))

  • 实现二:确保_new_()只返回一个instance,所以只制造了一个instance

    class User(object):

      __instance=None #私有的类属性
      
      def __init__(self,name):
          self.name=name
    
      def __new__(cls,name):
          if not cls.__instance:  #保证 __new__()返回的instance为恒定值,故而只有一个对象
              cls.__instance = super().__new__(cls)
          return cls.__instance
    

    u1 = User("zs")
    u2 = User("ls")
    print(u1.name,u2.name)
    print(u1==u2)

    ==判断表达式如果返回True,这两个对象是一个对象,并且内存地址相同

    print("u1对象的内存地址:%s,u2对象的内存地址:%s"%(id(u1),id(u2)))

    跟踪创建并初始化对象的过程:new(), init(), str(),

    u1 = User("zs")它先执行

    new的结果记为 I, 即 u1 == I

    init的结果就是 I.name = 'zs',或者说 u1.name = 'zs'

    此时还没有print(u1.name),所以不会激发str

    继续执行u2 = User("ls")

    new的结果也是: u2 == I, 那么此时 u2 == u1,进而u2.name == u1.name == 'zs'

    init的结果是 I.name = 'ls', 所以进而 u2.name = u1.name == I.name = 'ls'

    此时还没有print,所以str依旧没有激发,但是此刻 u1.name == u2.name == I.name = 'ls'

    继续执行 print(u1.name,u2.name),激发了str, 故而打印 u1.name == u2.name == I.name = 'ls'

3. 工厂模式

  • 帮助我们创建类的实例的一种方式,比直接new一个对象复杂
  • 但使系统的可维护性(后期代码的修改量尽可能小)和可扩展性更强
  • 当两个类的依赖关系已经存在的情况下,我们绝不可能干掉依赖关系。
    借助工厂模式,能让这种依赖关系的可维护性和可扩展性更强:找一个第三方(两个class中间插入接口,借助接口对话)

以一个“人使用斧头为例”,引入工厂之后:
人不需要自己new斧头,而是调用工厂,从工厂得到斧头
而工厂内部就实现了创造不同类型斧头的工作
这样人和斧头就有了工厂这个接口,以后人的class里面就不会具体涉及斧头class

  • 原始的做法:

    class Person(object):
    def init(self,name):
    self.name=name

      def work(self, axe_type): #人要传入斧头类型
          print(self.name+"开始工作了")
          #person完成work,需要使用一把斧头
    
          #在原始社会,人需要一把石
          #axe = StoneAxe("花岗岩斧头")
          #使用钢铁的斧
          axe = SteelAxe("加爵斧头")
          
          axe.cut_tree()
    

    class Axe(object):
    def init(self,name):
    self.name=name

      def cut_tree(self):
          print("%s斧头开始砍树"%self.name)
    

    class StoneAxe(Axe):
    def cut_tree(self):
    print("使用石头做的斧头砍树")

    class SteelAxe(Axe):
    def cut_tree(self):
    print("使用钢铁做的斧头砍树")

    p = Person("zs")

    p.work("Steel")

    p.work("Stone")

  • 简单工厂(工厂模式的简化版,使用了类的静态方法创建各种实例)

    class Person(object):
    def init(self,name):
    self.name=name

    def work(self, axe_type): #人要传入斧头类型
    print(self.name+"开始工作了")
    #person完成work,需要使用一把斧头

      #已经有工厂,person去找工厂生成一把斧头
      axe =Factory.create_axe(axe_type)
      axe.cut_tree()
    

    class Axe(object):
    def init(self,name):
    self.name=name

      def cut_tree(self):
          print("%s斧头开始砍树"%self.name)
    

    class StoneAxe(Axe):
    def cut_tree(self):
    print("使用石头做的斧头砍树")

    class SteelAxe(Axe):
    def cut_tree(self):
    print("使用钢铁做的斧头砍树")

    工厂类

    class Factory(object):
    #生产斧头,根据用户指定的类型来生产
    @staticmethod #支持在class外部,直接用类名调用
    def create_axe(axe_type):
    if (axe_type == 'Stone'):
    return StoneAxe("花岗岩斧头")
    elif (axe_type == 'Steel'):
    return SteelAxe("钢铁斧头")

    p = Person("zs")

    p.work("Steel")

    p.work("Stone")

  • 工厂模式(使用基本工厂的子类——各种具体工厂类,来分担SinpleFactory的静态方法创建各种实例的工作,更加抽象和更具有可维护性)

    class Person(object):
    def init(self,name):
    self.name=name

      def work(self):
          print(self.name+"开始工作了")
          #person完成work,需要使用一把斧头
    
          #已经有工厂,person去找工厂生成一把斧头
          factory = Steel_Axe_Factory() #即根据Person需求请求具体的工厂{具体工厂继承自基类工厂}
          #factory = Steel_Axe_Factory()
          axe =factory.create_axe()
          axe.cut_tree()
    

    class Axe(object):
    def init(self,name):
    self.name=name

      def cut_tree(self):
          print("%s斧头开始砍树"%self.name)
    

    class StoneAxe(Axe):
    def cut_tree(self):
    print("使用石头做的斧头砍树")

    class SteelAxe(Axe):
    def cut_tree(self):
    print("使用钢铁做的斧头砍树")

    工厂类

    class Factory(object):
    #生产斧头,根据用户指定的类型来生产
    def create_axe(self):
    pass

    class Stone_Axe_Factory(Factory):
    def create_axe(self):
    return StoneAxe("花岗岩斧头")

    class Steel_Axe_Factory(Factory):
    def create_axe(self):
    return SteelAxe("钢铁斧头")

    p = Person("zs")
    p.work() #如果需要改需求,去work()里面改换一个具体工厂即可,当然继续优化

原文地址:https://www.cnblogs.com/LS1314/p/8504454.html