我正在尝试替换简单工厂 StatsCreatorFactory.java 类,以便删除多次使用switch case语句的臭味。这是我的情况:
StatsServlet.java
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
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
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
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 Fawler的书我想知道我是否可以使用多态,但我找不到任何方法在我的代码中复制它。
答案 0 :(得分:2)
我首先尝试修改IStatsCreator和AbstractStatsCreator以获得无状态bean。
在您的示例中,您只需要删除在AbstractStatsCreator中定义为类变量的StatsContext上下文。所以上下文不应该绑定到类实例。当需要上下文的创建者调用方法时,它应该从外部传入。为此,您可以重构IStatsCreator并将上下文添加到需要它的所有方法中。
例如:
public IChart createChart()抛出IOException;
新:
public IChart createChart(StatsContext context)抛出IOException;
等等。 之后,您不必为每个上下文调用创建AbstractStatsCreator实现的新实例。你只需要每个类型有一个实例。这个类型的实例可以映射到StatsCreatorFactory中,只需在需要时获取。我还建议你去除静态方法。使StatsCreatorFactory成为一个真正的bean,可以更容易管理,也更容易被模拟测试。
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。
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);
}
}