简体   繁体   中英

Improve design of class hierarchy for a object formatter api

While learning object oriented design I'm judging my own design critically. This framework should be able to print objects in either XML, or JSON, I've stubbed in a basic implementation to avoid getting into details of XML and Json parser apis for now.

So I made the Formatter be the base class. But with my current design, all derivatives of this base class would need to know that they have to call: getFormattedValue() to get output. Also I don't feel comfortable with all of those if else statements in the Formatter constructor. The clients would need to know to pass in either an "xml" or "json" in all derivatives of this class. How can I improve this design to conform to all Object oriented design Principles? Thanks in advance..

public class Formatter {

    private String output;

    public Formatter(Object object, String formatType){
        if(formatType.equals("xml")){
            output = getXMLFormat(object);
        } else if(formatType.equals("json")) {
            output = getJSONFormat(object);
        }
    }

    private String getXMLFormat(Object object){

        return "<title>"+object.toString()+"<title>"; // simplified
    }

    private String getJSONFormat(Object object){
        return "{"+object.toString()+"}"; // simplified
    }

   protected  String getFormattedValue(){
        return output;
    }
}

The derivative class:

public class ItemFormatter extends Formatter {

    public ItemFormatter(Employee item, String formatOutput) {
        super(item, formatOutput);
    }

    public void printItem(){
        System.out.println(getFormattedValue());
    }
}

Split the formatting into multiple classes/interfaces and use a Factory/Factory method in order to get the appropriate formatter. It could look something like this:

public interface Formatter {
    String getFormattedValue();
}

and implement a JSonFormatter:

public class JSonFormatter implements Formatter {
    String getFormattedValue(Object object) {
        return "{"+object.toString()+"}";
    }
}

get the correct formatter:

public class FormatterFactory {
    public static Formatter getFormatter(String type) { // maybe use enum to decide
        if (type.equals("json") {
            return new JSonFormatter();
        } else if (type.equals("xml")) {
            return new XMLFormatter();
        }
        return new DefaultFormatter(); // returns toString for example
    }
}

and finally usage:

String formattedXML = FormatterFactory.getFormatter("xml").getFormattedValue("foobar");

I can't recommend anything for getFormattedValue() , you can probably change the method name to make it more obvious, but that's about it.

With regards to the xml and json, you can probably use Enums.

public Enum EnumFormatType {
    FORMAT_XML, FORMAT_JSON;
}

public Formatter(Object object, EnumFormatType formatType) {
   if(EnumFormatType.FORMAT_XML.equals(formatType)){
    // etc...
    }
}

I would start by providing a abstract class to format.

abstract class Formatter {
    String format(Object o);
}

Then we specialize two Formatter for XML and JASON

class XMLFormatter extends Formatter {
    String format(Object o) {
        return "<title>"+o.toString()+"<title>";
    }
}

Now you just have to choose which formater you need and just call format on any of them to get the right string.

I think the below code looks more extensible.

public interface IFormatter 
{
    String GetFormatted(Object object);
}

public class JSonFormatter extends IFormatter 
{
    public String GetFormatted(Object object)
    {
      return "{"+object.toString()+"}";
    }
}

public class XMLFormatter extends IFormatter 
{
    public String GetFormatted(Object object)
    {
        return "<title>"+object.toString()+"<title>";
    }
}

public class ItemFormatter 
{
    public void printItem(Employee item, IFormatter formatter)
    {    
        System.out.println(formatter.GetFormatted(item));
    }
}

And it can be called like

itemFormatterInsatnce.printItem(empInstance, formatterInstance);

Also the formatter instance can be resolved using a formatterFactory either through code or configuration.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM