【问题标题】:Two factory class to generate different interface instances with same condtion两个工厂类生成具有相同条件的不同接口实例
【发布时间】:2017-04-08 08:34:51
【问题描述】:

Java 程序

enum FILE_TYPE {
    XML, JSON;
}

interface Parser {
    void parse();
}
class XMLparser implements Parser {
    public void parse() { }
}
class JSONparser implements Parser {
    public void parse() { }
}

interface Mapper {
    void map();
}
class XMLmapper implements Mapper {
    public void map() { }
}
class JSONmapper implements Mapper {
    public void map() { }
}

class ParserFactory {
    public static Parser getInstance(FILE_TYPE fileType) {
        switch(fileType) {
        case XML:
            return new XMLparser();
        case JSON:
            return new JSONparser();
        }
        return null;
    }
}

class MapperFactory {
    public static Mapper getInstance(FILE_TYPE fileType) {
        switch(fileType) {
        case XML:
            return new XMLmapper();
        case JSON:
            return new JSONmapper();
        }
        return null;
    }
}

在上面的java程序中,两个工厂方法生成不同的接口实例都依赖于相同的条件,即都使用相同的枚举FILE_TYPE。

在这种情况下使用两个工厂方法是否正确? 约束是我不能将两个接口合二为一。

我是java设计的新手,请帮助我

【问题讨论】:

  • 你的命名完全违背了Java约定。类总是PascalCasecamelCase 为变量保留。 UPPER_SNAKE_CASE 保留用于编译时常量。请相应地更新您的代码。
  • 至于实际问题;我建议您使用getParsergetMapper 方法创建interface ParserMapper 或类似的方法。让您的工厂返回ParserMapper - 除非有任何理由将XmlMapperJsonParser 一起使用。
  • @BoristheSpider 你是对的,但想法是解析器本身将被其他模块重用,所以我将两者分开。
  • 然后将parserMapper.getParser 传递给该模块。有什么问题?!
  • enum FILE_TYPE - 这个名字还是错误的。见getInstance(FILE_TYPE fileType)

标签: java oop object design-patterns


【解决方案1】:

不,您当前的设计不正确。

您的代码显然违反了 open closed principle,也就是说,您最终会在太多地方出现 switch 语句,这不是一个好的设计,因为如果您想要添加 HTML 解析器(或稍后的其他解析器),您需要将 switch 语句添加到两个 Factory 类中。

解决方案是你需要使用抽象工厂模式,如下所示:

interface ContentHandler {
     public void parse();
     public void map();
}


public class XMLContentHandler implements ContentHandler {

    public void parse() { }

    public void map() { }
}


public class JSONContentHandler implements ContentHandler {

    public void parse() { }

    public void map() { }
}

class ContentFactory {
    public static ContentHandler getInstance(FILE_TYPE fileType) {
        switch(fileType) {
        case XML:
            return new XMLContentHandler();
        case JSON:
            return new JSONContentHandler();
        }
        return null;
    }
}

我不想将映射器实现共享给系统 重用解析器。

ParsingMapping 的职责应该由它们自己的类来处理(如XMLParserXMLMapperJSonParser 等),如下所示,这将符合single responsibility 原则。

public class XMLContentHandler implements ContentHandler {

        @Inject
        private XMLParser xmlParser;

        @Inject
        private XMLMapper xmlMapper;


        public void parse() { 
            xmlParser.parse();
        }

        public void map() { 
            xmlMapper.map();
        }
}

【讨论】:

  • 感谢您的回答。在此解析器将被系统中的其他模块重用。映射器实现将非常庞大,因此我不想将映射器实现共享给重用解析器的系统。
  • 我建议将XMLMapperImplXMLParserImpl注入上面的XMLHandler,然后职责是分开的。对于 JSON 也是如此
  • 我是一个非常新的面向对象的设计,你能不能给我一个小代码示例
  • 上面添加的代码示例
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-01-06
  • 2022-01-13
  • 1970-01-01
  • 2015-09-17
  • 2020-06-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多