抽象工厂模式

简介: 抽象工厂模式

业务场景

我们经常有这样子的代码

我们根据配置文件的后缀(json、xml、yaml、properties),选择不同的解析器(JsonRuleConfigParser、XmlRuleConfigParser……),将存储在文件中的配置解析成内存对象 RuleConfig

public RuleConfig load(String ruleConfigFilePath) {
        //根据文件获取文件后缀名
        String ruleConfigFileExtension = getFileExtension(ruleConfigFilePath);
        IRuleConfigParser parser = null;
        if ("json".equalsIgnoreCase(ruleConfigFileExtension)) {
            parser = new JsonRuleConfigParser();
        } else if ("xml".equalsIgnoreCase(ruleConfigFileExtension))  {
            parser = new XmlRuleConfigParser();
        } else if ("yaml".equalsIgnoreCase(ruleConfigFileExtension)) {
            parser = new YamlRuleConfigParser();
        } else if ("properties".equalsIgnoreCase(ruleConfigFileExtension)){
            parser = new PropertiesRuleConfigParser();
        } else
        {
            throw new InvalidRuleConfigException( "Rule config file format is not supported: " + ruleConfigFilePath)
        }
        String configText = "";
        //从ruleConfigFilePath文件中读取配置文本到configText中
         RuleConfig ruleConfig = parser.parse(configText);
         return ruleConfig;
    }

碰到这种非得要将 if 分支逻辑去掉,想到的解决方式就是利用工厂模式进行优化

工厂模式代码重构

解析器工厂接口

public interface IRuleConfigParserFactory {
    IRuleConfigParser createParser();
}

具体解析器工厂

public class JsonRuleConfigParserFactory implements IRuleConfigParserFactory {
    @Override
    public IRuleConfigParser createParser() {
        return new JsonRuleConfigParser();
    }
}
public class PropertiesRuleConfigParserFactory implements IRuleConfigParserFactory {
    @Override
    public IRuleConfigParser createParser() {
        return new PropertiesRuleConfigParser();
    }
}
public class XmlRuleConfigParserFactory implements IRuleConfigParserFactory {
    @Override
    public IRuleConfigParser createParser() {
        return new XmlRuleConfigParser();
    }
}
public class YamlRuleConfigParserFactory implements IRuleConfigParserFactory {
    @Override
    public IRuleConfigParser createParser() {
        return new YamlRuleConfigParser();
    }
}

工厂类实例集合

public static class RuleConfigParserFactoryMap {
        static  Map<String, IRuleConfigParserFactory> cachedFactories =new HashMap<String, IRuleConfigParserFactory>();
        static
        {
            cachedFactories.put("json", new JsonRuleConfigParserFactory());
            cachedFactories.put("xml", new XmlRuleConfigParserFactory());
            cachedFactories.put("yaml", new YamlRuleConfigParserFactory());
            cachedFactories.put("properties", new PropertiesRuleConfigParserFactory());
        }
    }

主方法

public static void main(String[] args) {
        IRuleConfigParserFactory parserFactory  =RuleConfigParserFactoryMap.cachedFactories.get("properties");
        parserFactory.createParser();
    }

这样就完成了

当对象的创建逻辑比较复杂,不只是简单的 new 一下就可以,而是要组合其他类对象,做各种初始化操作的时候,我们推荐使用工厂方法模式,将复杂的创建逻辑拆分到多个工厂类中,让每个工厂类都不至于过于复杂。而使用简单工厂模式,将所有的创建逻辑都放到一个工厂类中,会导致这个工厂类变得很复杂

除此之外,在某些场景下,如果对象不可复用,那工厂类每次都要返回不同的对象。如果使用简单工厂模式来实现,就只能选择第一种包含 if 分支逻辑的实现方式。如果还想避免烦人的 if-else 分支逻辑,这个时候,就推荐使用工厂方法模式

抽象工厂

在简单工厂和工厂方法中,类只有一种分类方式。比如,在规则配置解析那个例子中,解析器类只会根据配置文件格式(Json、Xml、Yaml……)来分类。但是,如果类有两种分类方式,比如,我们既可以按照配置文件格式来分类,也可以按照解析的对象(Rule 规则配置还是 System 系统配置)来分类,那就会对应下面这 8 个 parser 类

针对规则配置的解析器:基于接口
IRuleConfigParser 
JsonRuleConfigParser 
XmlRuleConfigParser 
YamlRuleConfigParser 
PropertiesRuleConfigParser
针对系统配置的解析器:基于接口
ISystemConfigParser 
JsonSystemConfigParser 
XmlSystemConfigParser 
YamlSystemConfigParser 
PropertiesSystemConfigParser

抽象工厂就是针对这种非常特殊的场景而诞生的。我们可以让一个工厂负责创建多个不同类型的对象(IRuleConfigParser、ISystemConfigParser 等),而不是只创建一种 parser对象。这样就可以有效地减少工厂类的个数。具体的代码实现如下所示

public interface IConfigParserFactory { 
IRuleConfigParser createRuleParser();
ISystemConfigParser createSystemParser(); 
//此处可以扩展新的parser类型,比如IBizConfigParser
}
public class JsonConfigParserFactory implements IConfigParserFactory {
    @Override 
    public IRuleConfigParser createRuleParser() {
        return new JsonRuleConfigParser(); 
    }
    @Override 
    public ISystemConfigParser createSystemParser() { 
        return new JsonSystemConfigParser(); 
    } 
}
public class XmlConfigParserFactory implements IConfigParserFactory { 
    @Override 
    public IRuleConfigParser createRuleParser() { 
        return new XmlRuleConfigParser();
        }
    @Override
    public ISystemConfigParser createSystemParser() {
        return new XmlSystemConfigParser(); 
    } 
}
////略.....

主启动类

public static void main(String[] args) {
        IConfigParserFactory configParserFactory=new JsonConfigParserFactory();
        IRuleConfigParser ruleConfigParser= configParserFactory.createRuleParser();
        ISystemConfigParser systemParser= configParserFactory.createSystemParser();
    }

抽象工厂模式面对的是一个组合体,但是有一种情况,会导致修改原有类,那就是当目标需要在解析器中新增一种解析器类型的时候,比如例子中,解析器组合中只包含SystemRule,如果再添加一种IBiz,那么所有的工厂包括工厂接口都面临修改

相关文章
|
1月前
|
设计模式 C#
C# 一分钟浅谈:工厂模式与抽象工厂模式
【10月更文挑战第10天】本文介绍了面向对象编程中的两种常见创建型设计模式:工厂模式和抽象工厂模式。工厂模式通过共同接口创建对象,隐藏创建逻辑,提高封装性和扩展性;抽象工厂模式则提供了一系列相关对象的创建接口,适用于多个相关产品族的创建。文章通过C#代码示例详细解释了这两种模式的实现和应用场景,并讨论了它们的优点、缺点及常见问题。
57 19
|
6月前
|
设计模式
工厂模式与抽象工厂模式
​ 如有错误或有补充,以及任何的改进意见,请在评论区留下您的高见 工厂模式 工厂模式是一种创建型设计模式。在工厂模式中,类的实例化过程通常是通过一个专门的工厂类来完成的,而不是直接在客户端代码中进行的。这样可以提供更好的封装,使得客户端代码与具体产品的实现解耦,增加代码的灵活性和可维护性。 优点 封装性:客户端代码不再需要知道所创建对象的详细信息,只需要与工厂接口进行交互即可。 灵活性:工厂模式使得系统更加灵活,可以在不修改客户端代码的情况下更换或添加新产品。 可扩展性:通过使用工厂模式,当需要添加新产品时,只需要扩展工厂类,而不需要修改客户端代码。 基本结构 抽象产品(Abstra
53 0
|
6月前
|
Java API 数据库
工厂方法模式
工厂方法模式
38 0
|
设计模式
2023-6-11-第二式抽象工厂模式
2023-6-11-第二式抽象工厂模式
75 0
|
设计模式 C++
2023-6-10-第一式工厂方法模式
2023-6-10-第一式工厂方法模式
83 0
|
设计模式 监控 uml
剖析工厂方法模式、从开电脑店开始
工厂类负责把实例化类时,复杂的过程透明化,同时避免大量实例化类的重复代码的出现。
剖析工厂方法模式、从开电脑店开始
|
设计模式 算法 搜索推荐
工厂方法模式的两个极端
概念:是一种常用的对象创建型设计模式,此模式的核心精神是封装类中不变的部分,提取其中个性化善变的部分为独立类,通过依赖注入以达到解耦、复用和方便后期维护拓展的目的。
|
设计模式
工厂方法模式详细介绍
工厂方法模式(Factory Method Pattern)是一种创建型设计模式,它提供了一种将对象的创建逻辑封装在工厂类中的方式,使得客户端代码无需直接依赖具体的类来创建对象。
105 0