工厂模式:设计模式系列(二)

  工厂模式(Factory Pattern):是定义一个用于创建对象的接口,但不指定其具体类,在需要创建实例的时候再由需求来决定的设计模式,归类为创建型模式。

  这一模式根据层次分类,可以分为以下几种:

  1. 简单工厂模式(Simple Factory Pattern)
  2. 工厂方法模式(Factory Method Pattern)
  3. 抽象工厂模式(Abstract Factory Pattern)

  这几种细分模式本质其实就是抽象,理解好他们的本质,就能很好地在使用这些模式的时候自由切换,而这写模式也体现了LSP、DIP、和ISP。

  简单工厂模式(Simple Factory Pattern):专门定义一个类来实例化其它类,被创建的实例通常都具有共同的父类或接口。这一模式建立思考过程相对简单,按照以下步骤进行:

  1. 现在需要几种对象,这些对象抽象出来的本质一样,可以把抽象出来后相同的属性和功能建立一个接口或协议。
  2. 但这些对象具体实例又具备细微的差异,可以通过已经建立了的接口或协议建立对应的实现类,由这些实现类进行适当的扩展。
  3. 由于这些实例对象都需要被调用,但逐个创建很麻烦,所以就创建一个工厂类,专门用来创建上面这些本质一样的实例对象。

  可以发现,简单工厂模式结构包含3个部分,接口或协议、具体实现类、可以创建其它类实例的类。

简单工厂模式示例代码如下(Swift语言):

protocol ObjectBluePrint{
    
    func show();
}

class Object1: ObjectBluePrint{
    
    func show() {
        print("Show object1");
    }
}

class Object2: ObjectBluePrint{
    
    func show() {
        print("Show object2");
    }
}

class Factory{
    
    func createObject(name:String)->ObjectBluePrint?{
        switch(name){
        case ("object1"):
            return Object1();
        case ("object2"):
            return Object2();
        default:
            return nil;
        }
    }
}

var factory = Factory();
var o1:ObjectBluePrint = factory.createObject("object1")!;
o1.show();
var o2:ObjectBluePrint = factory.createObject("object2")!;
o2.show();

  代码分析ObjectBluePrint是一个协议,用于表示多种对象的本质,也就是各种实现类都应该具备的功能,这里写了2个实现类,Object1Object2,他们之间有细微的区别,而在下面,有一个Factory的实现类,类中方法createObject能基于ObjectBluePrint创建具体需要的实例对象,上面的代码中输出结果如下:

Show object1
Show object2

  工厂方法模式(Factory Method Pattern):则是在简单工厂模式之上,把工厂抽象化,使工厂类分为接口或协议、具体实现两部分,可以想象,这么做的原因是工厂有可能有很多个,而多个工厂之间也有细微的区别。这时候,建立思考过程在简单工厂模式上进行一点的添加修改即可:

  1. 现在需要几种对象,这些对象抽象出来的本质一样,可以把抽象出来后相同的属性和功能建立一个接口或协议。
  2. 但这些对象具体实例又具备细微的差异,可以通过已经建立了的接口或协议建立对应的实现类,由这些实现类进行适当的扩展。
  3. 由于这些实例对象都需要被调用,但逐个创建很麻烦,于是需要创建工厂类来进行创建,但是同一工厂创建出来的对象是一样的,为了创建出具有各自工厂特色的对象,需要把工厂抽象出来建立一个代表本质的接口或协议。
  4. 那么现在有了工厂的本质了,就需要把工厂实例化,最终达到创建实例对象的目的。

  可以发现,相对于简单工厂模式,工厂方法模式多了一个部分,对象的接口或协议、对象的实现类、工厂的接口或协议、工厂的实现类。

工厂方法模式示例代码如下(Swift语言):

protocol ObjectBluePrint{
    
    func show();
}

class Object1: ObjectBluePrint{
    
    func show() {
        print("Show object1");
    }
}

class Object2: ObjectBluePrint{
    
    func show() {
        print("Show object2");
    }
}

class Object3: ObjectBluePrint{
    
    func show() {
        print("Show object3");
    }
}

class Object4: ObjectBluePrint{
    
    func show() {
        print("Show object4");
    }
}

protocol FactoryBluePrint{
    
    func createObject(name:String)->ObjectBluePrint?;
}

class Factory1: FactoryBluePrint{
    
    func createObject(name:String)->ObjectBluePrint?{
        switch(name){
        case ("object1"):
            return Object1();
        case ("object2"):
            return Object2();
        default:
            return nil;
        }
    }
}

class Factory2: FactoryBluePrint{
    
    func createObject(name:String)->ObjectBluePrint?{
        switch(name){
        case ("object3"):
            return Object3();
        case ("object4"):
            return Object4();
        default:
            return nil;
        }
    }
}

var factory1:FactoryBluePrint = Factory1();
var o1:ObjectBluePrint = factory1.createObject("object1")!;
o1.show();
var o2:ObjectBluePrint = factory1.createObject("object2")!;
o2.show();

var factory2:FactoryBluePrint = Factory2();
var o3:ObjectBluePrint = factory2.createObject("object3")!;
o3.show();
var o4:ObjectBluePrint = factory2.createObject("object4")!;
o4.show();

  代码分析:可以发现,上面的代码是基于简单工厂模式,添加了FactoryBluePrint协议,为了显示出区别把Factory实现类分为Factory1Factory2,这时因为两个工厂的不一样,所以可以根据各自工厂的特色创建对象了,上面的代码中输出结果如下:

Show object1
Show object2
Show object3
Show object4

  抽象工厂模式(Abstract Factory Pattern):抽象工厂模式是工厂方法模式在创建对象结构方面的升级,可以从工厂方法模式中看到,所有创建的对象都具有同一接口或协议(可以理解为对象具有同一本质),而在抽象工厂模式中,工厂将要创建的对象具有不一样的接口和协议(理解为对象本质不一样),这时候,建立思考过程在工厂方法模式上进行一点的添加修改即可:

  1. 现在需要几种对象,这些对象抽象出来的本质不一样,可以把抽象出来后相同的属性和功能建立一个接口或协议,而不一样的属性和功能建立另一个接口或协议。
  2. 在这些对象中具体实例又具备细微的差异,可以通过已经建立了的接口或协议建立对应的实现类,由这些实现类进行适当的扩展。
  3. 由于这些实例对象都需要被调用,但逐个创建很麻烦,于是需要创建工厂类来进行创建,但是同一工厂创建出来的对象是一样的,为了创建出具有各自工厂特色的对象,需要把工厂抽象出来建立一个代表本质的接口或协议。
  4. 那么现在有了工厂的本质了,就需要把工厂实例化,最终达到创建实例对象的目的。

  可以发现,抽象工厂模式跟工厂方法模式具有一样的分类,对象的接口或协议、对象的实现类、工厂的接口或协议、工厂的实现类,不同之处在于对象的接口或协议是多个的而非一个。

抽象工厂模式示例代码如下(Swift语言):

protocol ObjectBluePrint1{
    
    func show();
}

class Object1: ObjectBluePrint1{
    
    func show() {
        print("Show object1");
    }
}

class Object2: ObjectBluePrint1{
    
    func show() {
        print("Show object2");
    }
}
protocol ObjectBluePrint2{
    
    func tell();
}

class Object3: ObjectBluePrint2{
    
    func tell() {
        print("tell object3");
    }
}

class Object4: ObjectBluePrint2{
    
    func tell() {
        print("tell object4");
    }
}

protocol FactoryBluePrint{
    
    func createObject(name:String)->ObjectBluePrint1?;
    
    func createObject(name:String)->ObjectBluePrint2?;
}

class Factory1: FactoryBluePrint{
    
    func createObject(name:String)->ObjectBluePrint1?{
        switch(name){
        case ("object1"):
            return Object1();
        default:
            return nil;
        }
    }
    
    func createObject(name:String)->ObjectBluePrint2?{
        switch(name){
        case ("object3"):
            return Object3();
        default:
            return nil;
        }
    }

}

class Factory2: FactoryBluePrint{
    
    func createObject(name:String)->ObjectBluePrint1?{
        switch(name){
        case ("object2"):
            return Object2();
        default:
            return nil;
        }
    }
    func createObject(name:String)->ObjectBluePrint2?{
        switch(name){
        case ("object4"):
            return Object4();
        default:
            return nil;
        }
    }
}


var factory1:FactoryBluePrint = Factory1();
var o1:ObjectBluePrint1 = factory1.createObject("object1")!;
o1.show();
var o3:ObjectBluePrint2 = factory1.createObject("object3")!;
o3.tell();

var factory2:FactoryBluePrint = Factory2();
var o2:ObjectBluePrint1 = factory2.createObject("object2")!;
o2.show();
var o4:ObjectBluePrint2 = factory2.createObject("object4")!;
o4.tell();

  代码分析:可以发现,上面的代码是基于工厂方法模式,修改了ObjectBluePrint协议为ObjectBluePrint1,增加了ObjectBluePrint2,并且在FactoryBluePrint中区分了创建对象的类型,为了显示出区别把Factory实现类中创建对象的方法重载,这样就能看出多种对象接口或协议对应的对象被创建出来的区别了,上面的代码中输出结果如下:

Show object1
tell object3
Show object2
tell object4

  总结:工厂模式是非常常用的一种设计模式,也很严格地遵循和体现了LSP、DIP,对于降低耦合作用很大。重点在于对工厂和创建对象的本质的抽象,而难点则是在持续对模式相关代码的扩展中,理解好本质,在使用的时候会发现这其实能一定程度上提升开发效率。


lZackx © 2022. All rights reserved.

Powered by Hydejack v9.1.6