一瞥之见

0%

创建类实例

文章结构说明

下面将从简单到复杂的说明,实例化类有哪些方式、会说明每种方式的优势和弊端是什么

前言
请先确保能读懂UML类图。UML类图基础 可参考

创建类实例的演进过程

构造器 [如new和__init__() ]

存在的问题:可能一个类能够使用多种初始化的方式
如可以使用两种方法描述一个点的位置:笛卡尔坐标系 与 极坐标系
Point(double x, double y)
Point(double r, double theta)

静态方法

  • 优点
    • 不同参数初始化实例
      在类Point中写两个对应的静态方法用于创建即可、使用时如下:
      ​ Point p1 = Ponit.cartesian(1, 2)
      ​ Point p2 = Point.polar(1.0, Mth.PI/3)
    • 不同调用方式
      如python里不能await __init__方法、但可以通过await一个静态async方法实现

简单工厂/静态工厂 模式

  • 优点:
    • 类型隐藏
      使用构造方法时、明确的返回对应调用类型的实例、这就违背了面向接口编程的原则
      相反使用静态工厂方法的时候就可以返回一个满足对应接口的对象而不用透露具体的对象给客户(从而此类型可以是公开/非公开/甚至动态加载的)
      如:假设一个规则解析的类群(Parser <— JsonParser、XmlParser, …),则此时能够如下进行解藕
  • 对应UML图
    easy_factory
  • 缺点:
    • 工厂类的职责成为了对接外部参数并且依据这些参数进行创建具体类的职责,所有的类的创建逻辑都集中在了这里面,从而导致在添加新的类的时候一定需要修改此创建方法(违背开闭原则);特别需要注意的是在发展的过程中,有可能出现不同具体类的创建依赖不同条件的情况,此会导致这唯一工厂类的逻辑复杂并降低可维护性

工厂方法

  • 核心思维:新加抽象工厂约束具体工厂对外提供的接口、并且将具体类型的创建延迟到工厂子类来完成,这样就解藕了上面提到的不同初始化具体类时的逻辑太过于纠缠到一个方法内可维护性不高的问题
  • 举例:假设我们要可以选择初始化的选择是一些key-val数据库(redis、leveldb、rocksdb…),然后通过传入的参数进行返回对应的连接。
    factory_methos
  • 优点
    • 保持了NosqlClientFactoryMap.get_conn方法中的简洁,其只做具体NosqlClientFactory实现类的定位以及参数透传,具体各个实现类要用哪些参数进行初始化链接便自己内部进行相关逻辑处理
    • 我这里特意为Nosql的添加了create_conn方法,是对于每种Nosql DB我们都明确的知道需要哪些参数来创建、故放到自己的类下面进行维护是更为清晰合理的,而此时对应的子类XxxFactory就只需要构造出这样的参数并调用之就可以了,这样的好处就是假设别的地方又需要创建Nosql客户端时(假设要创建Redis客户端),就可以自己依据自己这边的输入进行构造Redis.create_conn需要的参数进行调用。这样就分离了变化(创建核心参数 与 变化的不同地方不同输入参数的有效化处理过程)
  • 缺点
    • 需要创建的子factory类太多

抽象工厂

  • 核心要点:主要用于解决“隔离域”问题,在工厂方法中,用户调用外层工厂NosqlClientFactoryMap是有权限创建任意一种具体Nosql产品的,并没有从NosqlClientFactoryMap级别进行隔离,而抽象工厂要做的就是从最外界进行隔离,让不同“环境”的用户调用的最外层工厂类只能创建到其特定被赋予的组件
  • 举例2:假设有一个产品,其分内网使用与外网使用、而其使用到的组件有关系型数据库以及消息队列组件,假设其内网使用的全部是自研的产品如关系型数据库A与消息队列组件A,而外网使用的则是通用的mysql和ActiveMQ,那么就会出现实例化时需要实例化不同的族的问题。从图中可以看到,内网用户只能调用InnerFactory,而后其如果想获取RDB则在调用对应的createRDB获取,同理当需要使用时候调用createMQ,这样就从最外层的创建者做了隔离
  • 其UML如下
    abstract_factory
  • 补充:“隔离域”不要只想到环境问题,还有比如类似假设一个系统的用户相关使用的是一组资源类型、而交易相关的使用的是另一租资源类型
  • 补充:一个思考是其实还可以将工厂方法也揉入进来,这里假设内网用户可创建的RDB也有多种选择,这样在InnerFactory这个层级下又可以添加子类工厂进行将实例化推迟到子类工厂

参考

《冒号课堂》第13章第1节
创建型模式