工厂设计模式

简介

当创建对象的代码多而杂时,可以用工厂模式将对象的创建和使用分离,让代码更加清晰。

比如下面代码根据不同的 rule 创建不同的对象。

java demo


public class Demo {

    // 解析文件,返回解析内容

    public void load(String rule) {

        IParse parse = null;

        // 根据不同的文件类型,执行不同的内容

        // 分析:如果代码中创建对象的过程很复杂,就需要把这段代码移出去,单独封装成类,封装的类就是工厂类

        if ("xml".equals(rule))

            parse = new XmlParse();

        else if ("json".equals(rule))

            parse = new JsonParse();

        else if ("excel".equals(rule))

            parse = new ExcelParse();

        else if ("csv".equals(rule))

            parse = new CsvParse();

        else

            parse = new OtherParse();

        // parse 是解析类之一,具体是哪一个,要根据 rule 来决定

        parse.parse();

        // 省略其它有关 load 的大量操作

    }

    public static void main(String[] args) {

        Demo demo = new Demo();

        // 传入 json

        demo.load("json");

    }

}

// 所有解析类的接口,规定解析类的方法

interface IParse {

    // 需要解析类去实现

    public void parse();

}

class XmlParse implements IParse {

    // 解析结果

    public void parse() {

        System.out.println("XmlParse");

    }

}

class JsonParse implements IParse {

    public void parse() {

        System.out.println("JsonParse");

    }

}

class ExcelParse implements IParse {

    public void parse() {

        System.out.println("ExcelParse");

    }

}

class CsvParse implements IParse {

    public void parse() {

        System.out.println("CsvParse");

    }

}

class OtherParse implements IParse {

    public void parse() {

        System.out.println("OtherParse");

    }

}

python demo


# Demo 用于加载不同的文件,对不同的文件作不同的处理 

class Demo:

    def load(self, rule):

        parse = None

        # 根据不同的 rule ,创建不同的对象

        if "xml" == rule:

            parse = XmlParse()

        elif "json" == rule:

            parse = JsonParse()

        elif "excel" == rule:

            parse = ExcelParse()

        elif "csv" == rule:

            parse = CsvParse()

        else:

            parse = OtherParse()

        # 调用对象的方法进行操作

        parse.parse()

# 相当于接口,用于规范各个解析类

# 每个解析类都要实现 parse 方法,否则在调用的时候就会报错

class IParse:

    def parse(self):

        raise ValueError()

class XmlParse(IParse):

    def parse(self):

        print("XmlParse")

class JsonParse(IParse):

    def parse(self):

        print("JsonParse")

class ExcelParse(IParse):

    def parse(self):

        print("ExcelParse")

class CsvParse(IParse):

    def parse(self):

        print("CsvParse")

class OtherParse(IParse):

    def parse(self):

        print("OtherParse")

if __name__ == "__main__":

    Demo().load("json")

简单工厂

把创建大量实例的代码放到工厂类中。

java 实现


public class Demo {

    // 解析文件,返回解析内容

    public void load(String rule) {

        IParse parse = ParseFactory.createParse(rule);

        // parse 是解析类之一,具体是哪一个,要根据 rule 来决定

        parse.parse();

        // 省略其它有关 load 的大量操作

    }

    public static void main(String[] args) {

        Demo demo = new Demo();

        // 传入 json

        demo.load("json");

    }

}

// 简单工厂:把创建对象的代码移动到这个类中的一个方法,这个类就叫做简单工厂

// 简单工厂的类名字通常以 Factory 结尾

// 简单工厂的方法,通常叫 createParse

class ParseFactory {

    public static IParse createParse(String rule) {

        IParse parse = null;

        // 根据不同的文件类型,执行不同的内容

        if ("xml".equals(rule))

            parse = new XmlParse();

        else if ("json".equals(rule))

            parse = new JsonParse();

        else if ("excel".equals(rule))

            parse = new ExcelParse();

        else if ("csv".equals(rule))

            parse = new CsvParse();

        else

            parse = new OtherParse();

        return parse;

    }

}

    // 所有解析类的接口,规定解析类的方法

    interface IParse {

        // 需要解析类去实现

        public void parse();

    }

    class XmlParse implements IParse {

        // 解析结果

        public void parse() {

            System.out.println("XmlParse");

        }

    }

    class JsonParse implements IParse {

        public void parse() {

            System.out.println("JsonParse");

        }

    }

    class ExcelParse implements IParse {

        public void parse() {

            System.out.println("ExcelParse");

        }

    }

    class CsvParse implements IParse {

        public void parse() {

            System.out.println("CsvParse");

        }

    }

class OtherParse implements IParse {

    public void parse() {

        System.out.println("OtherParse");

    }

}

python 实现


# Demo 用于加载不同的文件,对不同的文件作不同的处理 

# 问题:如果创建对象的代码比如多,可能还会创建 text ,md,yml 等等

# 简单工厂解决:把对象的创建移动到其它类中, load 方法就会很简洁

class Demo:

    def load(self, rule):

        parse = ParseRuleFactory().create_parse(rule)

        # 调用对象的方法进行操作

        parse.parse()

# 简单工厂类:用于实例的创建,根据 rule 创建不同的实例。本质就是把 Demo 中原来创建实例的代码,给迁移过来

class ParseRuleFactory:

    def create_parse(self, rule):

        parse = None

        # 根据不同的 rule ,创建不同的对象

        if "xml" == rule:

            parse = XmlParse()

        elif "json" == rule:

            parse = JsonParse()

        elif "excel" == rule:

            parse = ExcelParse()

        elif "csv" == rule:

            parse = CsvParse()

        else:

            parse = OtherParse()

        return parse

        

# 相当于接口,用于规范各个解析类

# 每个解析类都要实现 parse 方法,否则在调用的时候就会报错

class IParse:

    def parse(self):

        raise ValueError()

class XmlParse(IParse):

    def parse(self):

        print("XmlParse")

class JsonParse(IParse):

    def parse(self):

        print("JsonParse")

class ExcelParse(IParse):

    def parse(self):

        print("ExcelParse")

class CsvParse(IParse):

    def parse(self):

        print("CsvParse")

class OtherParse(IParse):

    def parse(self):

        print("OtherParse")

if __name__ == "__main__":

    Demo().load("json")

工厂方法

如果创建实例的代码非常复杂,就可以把创建实例的代码单独放入一个类。

比如下面的例子,创建实例代码复杂:

java 实现


public class Demo {

    // 如果创建对象时,代码很复杂,简单工厂就不能解决问题,因为即使使用简单工厂,创建实例依旧很复杂

    // 此时就需要工厂方法来解决、

    // 工厂方法解决方案:将每一个创建过程都封装到工厂类中

    // 比如下面的 JsonParseRuleFactory ,将复杂的代码都放到了 JsonParseRuleFactory 类中

    public void load(String rule) {

        IParse parse = null;

        if ("xml".equals(rule))

            // 省略了 1000 行代码

            parse = new XmlParse();

        else if ("json".equals(rule))

            parse = new JsonParseRuleFactory().createParse();

        else if ("excel".equals(rule))

            // 省略了 1000 行代码

            parse = new ExcelParse();

        else if ("csv".equals(rule))

            // 省略了 1000 行代码

            parse = new CsvParse();

        else

            // 省略了 1000 行代码

            parse = new OtherParse();

        // parse 是解析类之一,具体是哪一个,要根据 rule 来决定

        parse.parse();

        // 省略其它有关 load 的大量操作

    }

    public static void main(String[] args) {

        Demo demo = new Demo();

        // 传入 json

        demo.load("json");

    }

}

// 工厂方法的接口:要根据不同的调用,实现不同的操作

interface IParseRuleFactory {

    // createParse 接口要创建对象以及复杂操作

    public IParse createParse();

}

// 把原来 json 处理的所有代码,都迁移过来

class JsonParseRuleFactory implements IParseRuleFactory {

    public IParse createParse() {

        // 省略了 1000 行代码

        return new JsonParse();

    }

}

// 所有解析类的接口,规定解析类的方法

interface IParse {

    // 需要解析类去实现

    public void parse();

}

class XmlParse implements IParse {

    // 解析结果

    public void parse() {

        System.out.println("XmlParse");

    }

}

class JsonParse implements IParse {

    public void parse() {

        System.out.println("JsonParse");

    }

}

class ExcelParse implements IParse {

    public void parse() {

        System.out.println("ExcelParse");

    }

}

class CsvParse implements IParse {

    public void parse() {

        System.out.println("CsvParse");

    }

}

class OtherParse implements IParse {

    public void parse() {

        System.out.println("OtherParse");

    }

}

python 实现


# 问题:简单工厂不能解决创建实例的代码可能很复杂,即使迁移到了简单工厂中,复杂的创建过程依旧存在

# 解决:使用工厂方法,把创建过程封装到工厂类

class Demo:

    def load(self, rule):

        parse = None

        if "xml" == rule:

            # 省略 1000 行代码

            parse = XmlParse()

        elif "json" == rule:

            parse = JsonParseRuleFactory().create_parse()

        elif "excel" == rule:

            # 省略 1000 行代码

            parse = ExcelParse()

        elif "csv" == rule:

            # 省略 1000 行代码

            parse = CsvParse()

        else:

            # 省略 1000 行代码

            parse = OtherParse()

        # 调用对象的方法进行操作

        parse.parse()

# 相当于接口,用于规范各个工厂类

class IParseRuleFactory:

    def create_parse(self):

        raise ValueError()

# 工厂:把 Json 的解析放到此工厂下面

class JsonParseRuleFactory (IParseRuleFactory):

    def create_parse(self):

        # 省略 1000 行代码

        return JsonParse()

# 相当于接口,用于规范各个解析类

# 每个解析类都要实现 parse 方法,否则在调用的时候就会报错

class IParse:

    def parse(self):

        raise ValueError()

class XmlParse(IParse):

    def parse(self):

        print("XmlParse")

class JsonParse(IParse):

    def parse(self):

        print("JsonParse")

class ExcelParse(IParse):

    def parse(self):

        print("ExcelParse")

class CsvParse(IParse):

    def parse(self):

        print("CsvParse")

class OtherParse(IParse):

    def parse(self):

        print("OtherParse")

if __name__ == "__main__":

    Demo().load("json")

抽象工厂

假设有 A 公司, B 公司,C 公司… 都要有自己的解析方法,比如:A 公司有 AXmlParseFactory ,B 公司有 BXmlParseFactory ,C 公司有 CXmlParseFactory 。如果此时使用简单工厂和工厂方法,工作量非常大,因为要给每一个公司都创建所有的解析工厂。

此时可以用抽象工厂解决问题。解析工厂返回多个实例,比如,XmlParseFactory 可以返回 A ,B , C 的实例。

java 实现


// 抽象工厂:使工厂类具有返回多个实例的功能

interface IParseRuleFactory {

    public IParse AcreateParse();

    public IParse BcreateParse();

    public IParse CcreateParse();

}

class XmlParseRuleFactory implements IParseRuleFactory{

    public IParse AcreateParse() {}

    public IParse BcreateParse(){}

    public IParse CcreateParse(){}

}

python 实现


# 问题:如果多个公司都要封装工厂,比如 A, B, C ...公司都要封装自己的工厂,就要封装 n 个工厂类

# 解决:可以使用抽象工厂解决问题,每个工厂类可以创建多个实例,比如 JsonParseRuleFactory ,可以创建 A, B, C 公司的实例

# 一个工厂类,可以生成多个公司的解析方法

class IParseRuleFactory:

    def a_create_parse(self):

        raise ValueError()

    def b_create_parse(self):

        raise ValueError()

    def c_create_parse(self):

        raise ValueError()

    

# 实现时候,一个工厂类就可以生成多个公司的实例

class JsonParseRuleFactory(IParseRuleFactory):

    def a_create_parse(self):

        """

        """

    def b_create_parse(self):

        """

        """

        

    def c_create_parse(self):

        """

        """