首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用多态性替换简单工厂

使用多态性替换简单工厂
EN

Stack Overflow用户
提问于 2015-06-05 09:16:22
回答 1查看 104关注 0票数 0

我试图替换简单的工厂StatsCreatorFactory.java类,以便删除开关case语句的臭味多次使用。这就是我的处境:

StatsServlet.java

代码语言:javascript
复制
public class StatsServlet extends HttpServlet{ 

    private static final long serialVersionUID = 1L;

    protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        StatsContext context = new StatsContext(request,response);
        **IStatsCreator creator = StatsCreatorFactory.getCreator(context);**
        IChart chart = creator.createChart();
        String jsonChart = creator.chartToJson(chart);
        creator.sendResponse(jsonChart);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        processRequest(request, response);
    }

}

IStatsCreator.java

代码语言:javascript
复制
public interface IStatsCreator {

    public IChart createChart() throws IOException;
    public  IDetailsTable createDetailsTable(String itemSelected);

    public String chartToJson(IChart chart);
    public String tableToJson(IDetailsTable table);

    public void sendResponse(String resp) throws IOException;


    public List<File> findFiles() throws IOException, ParseException;
    public List<LogLine> parseFiles(List<File> files) throws IOException;
    public IFileIntervalDateDetector getFileDetector() throws IOException;

    public TargetChartOperation getTargetOperation();
    public IChart getChart();
    public IDetailsTable getDetailsTable();
}

AbstractStatsCreator

代码语言:javascript
复制
public abstract class AbstractStatsCreator implements IStatsCreator{

    protected StatsContext context;

    public AbstractStatsCreator(StatsContext context) {
        this.context = context;
    }

    protected abstract ILogParser getParser();
    protected abstract IStatsHelper getHelper();

    @Override
    public IFileIntervalDateDetector getFileDetector() throws IOException {
        IFileIntervalDateDetector fileDetector = new FileDetector();
        fileDetector.addPattern(new FileNamePattern(TypeSubjectEnum.valueOf(context.getSubject().toUpperCase()).getFilePattern()));
        fileDetector.addPattern(new FileNamePattern(context.getInstance()));
        return fileDetector;
    }

    @Override
    public final List<File> findFiles() throws IOException, ParseException{
        if(context.getDateStart().equalsIgnoreCase(StringUtils.EMPTY) && context.getDateEnd().equalsIgnoreCase(StringUtils.EMPTY)){
            return getFileDetector().findDailyFiles();
        }

        Date startDate = new SimpleDateFormat("ddMMyyyy").parse(context.getDateStart());
        Date stopDate = new SimpleDateFormat("ddMMyyyy").parse(context.getDateEnd());
        Date currentDate = new Date(System.currentTimeMillis());

        if(DateUtils.isSameDay(startDate, stopDate) && DateUtils.isSameDay(startDate, currentDate)){
            return getFileDetector().findDailyFiles();
        }

        return getFileDetector().findFilesByInterval(context.getDateStart(), context.getDateEnd()); 
    }

    @Override
    public final List<LogLine> parseFiles(List<File> files) throws IOException{
        return getParser().parseLogFiles(files);
    }

    @Override
    public IChart createChart() throws IOException{

        if(context.needUpdate()){
            List<File> files = null;
            try {
                files = findFiles();
            } catch (ParseException e) {
                files=Lists.newArrayList();
            }
            List<LogLine> logLines = parseFiles(files);
            context.setLogLines(logLines);
            context.updateContext(); 
        }

        IChart chart = getChart().create();
        return chart;
    }

    @Override
    public IDetailsTable createDetailsTable(String itemSelected) {
        IDetailsTable table = getDetailsTable().create(itemSelected);
        return table;
    }

    @Override
    public String chartToJson(IChart chart) {
        StringBuilder json = new StringBuilder(JsonTransformer.renderChart(chart));
        return json.toString();
    }

    @Override
    public String tableToJson(IDetailsTable table) {
        StringBuilder json = new StringBuilder(JsonTransformer.renderDetailsTable(table));
        return json.toString();
    }

    @Override
    public void sendResponse(String resp) throws IOException {
        context.getResponse().setContentType("application/json");
        PrintWriter out = context.getResponse().getWriter();
        out.write(resp.toString());
        out.flush();
    }

}

StatsCreatorFactory.java

代码语言:javascript
复制
public class StatsCreatorFactory {

    public static IStatsCreator getCreator(StatsContext context){

        if(context == null){
            throw new IllegalArgumentException("Context nullo");
        }

        IStatsCreator creator=null;

        switch (context.getOperation()) {
        case "validate":
            creator = new ValidateStatsCreator(context);
            break;
        case "extract":
            creator = new ExtractStatsCreator(context);
            break;
        case "transform":
            creator = new TransformStatsCreator(context);
            break;
        case "view":
            creator = new ViewStatsCreator(context);
            break;  
        default:
            creator = new GeneralStatsCreator(context);
            break;
        }

        return creator;
    }
}

我会试图找到一种方法来实例化ICreator类,避免简单的工厂类,是否可以使用任何重构或设计模式?阅读Martin的书,我想知道我是否可以使用多态性,但我找不到在代码中复制它的任何方法。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-06-05 09:41:47

首先,我将尝试修改IStatsCreator和AbstractStatsCreator,使其具有无状态bean。

在您的示例中,您只需去掉定义为StatsContext中的类变量的AbstractStatsCreator上下文。因此,不应该将上下文绑定到类实例。当对需要上下文的创建者调用方法时,它应该从外部传入。为此,您可以重构IStatsCreator并将上下文添加到所有需要它的方法中。

例如:

公共IChart createChart()抛出IOException;

新:

公共IChart createChart( StatsContext context )抛出IOException;

诸若此类。之后,您不必为每个上下文调用创建新的AbstractStatsCreator实现实例。您只需要每种类型都有一个实例。这个类型的实例可以在StatsCreatorFactory中映射,并在需要时得到。我也要改掉静态的方法。让StatsCreatorFactory成为一个真正的bean,它可以更容易地被管理,也可以更容易地在测试中被模仿。

代码语言:javascript
复制
public class StatsCreatorFactory {

    private Map<String, IStatsCreator> statsCreators = new HashMap<String, IStatsCreator>();

    public void registerStatsCreator( String type, IStatsCreator creator ) {
        statsCreators.put( type, creator );
    }

    public IStatsCreator getCreator( String type ){

        IStatsCreator creator= statsCreators.get( type );

        if(creator == null){
            throw new IllegalArgumentException("no creator registered for type : " + type);
        }

        return creator;
    }

}

最后,StatsCreatorFactory更像是提供者,而不是工厂。也许您也可以将它重命名为StatsCreatorProvider。

代码语言:javascript
复制
public class StatsServlet extneds HttpServlet{

private static final long serialVersionUID = 1L;

private StatsCreatorProvider statsCreatorProvider;

public void init() {
    statsCreatorProvider = new StatsCreatorProvider();
    statsCreatorProvider.registerStatsCreator( "validate", new ValidateStatsCreator() );
    statsCreatorProvider.registerStatsCreator( "extract" new ExtractStatsCreator() );
    ...
}

protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    StatsContext context = new StatsContext(request,response);
    IStatsCreator creator = statsCreatorProvider.getCreator( context.getOperation() );
    IChart chart = creator.createChart( context );
    String jsonChart = creator.chartToJson(chart);
    creator.sendResponse(jsonChart);
}

@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    processRequest(request, response);
}

}

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30662770

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档