O padrão "simple" factory fornece uma forma de criar objectos a partir de uma descrição externa.
O processo de criação de objectos a partir de texto é um processo semelhante à compilação e implica interpretar esse texto e construir a semântica.
<text> PERSON|1|Luke Skywalker|wimp@resistance.org|123-456-789 PERSON|2|Darth Vader|vader@imperial.net|911 PERSON|3|Master Yoda|yoda@jedi.edu|1 PERSON|4|Montgomery Scott|scotty@starfleet.net|987-654-321 PERSON|5|James T. Kirk|kirk@starfleet.net|987-654-321 PERSON|6|Jean-Luc Picard|picard@starfleet.net|987-123-654 ORGANIZATION|7|Google|noreply@google.com|0 ORGANIZATION|8|Melkor & Sauron’s|recruiting@utumno.com|999 ORGANIZATION|9|Starfleet|info@starfleet.net|999 MESSAGE|10|1|3|cities|look at this http://bit.ly/p0XoDW MESSAGE|11|2|1|we have to talk|Luke, I’m your father! MESSAGE|12|1|2|Re: we have to talk|Nooooooooooo!!!! MESSAGE|13|5|4|Teleporter|Beam me up, Scotty! MESSAGE|14|6|4|Teleporter|Beam me up, Scotty! NOTE|15|3|Cookies|Mix everything and apply a little Force for 30 seconds NOTE|16|4|Dilithium crystals|Remember never to put them in the freezer URI|17|1|Angry Ewoks|http://jedi.edu/ewoks/ URI|18|2|Imperial Bank|http://bank.imperial.net/ IMAGE|19|1|Tatooine|[desert scene with two suns setting] CONNECTION|1|2|0|1 CONNECTION|1|3|1|1 CONNECTION|4|5|1|1 CONNECTION|4|6|1|1 </text>
Os formatos são os seguintes. <text> PERSON|id|name|email|phone ORGANIZATION|id|name|email|phone MESSAGE|id|from|to|subject|body NOTE|id|owner|title|text IMAGE|id|owner|description|content URI|id|owner|description|uri CONNECTION|id1|id2|id1-accepting?|id2-accepting? </text>
Função principal de leitura do ficheiro com a informação textual (no projecto, este ficheiro é tipicamente passado ao programa através da propriedade "import").
<java5> class Network {
//... void readImportFile(String name) throws IOException { BufferedReader reader = new BufferedReader(new FileReader(name)); String line; while ((line = reader.readLine()) != null) { String[] fields = line.split("\\|"); try { registerFromFields(fields); } catch (UnknownDataException e) { System.err.printf("WARNING: unknown data %s\n", e.getMessage()); e.printStackTrace(); } catch (PublicationExistsException e) { e.printStackTrace(); } catch (UnknownAgentException e) { e.printStackTrace(); } catch (ClientExistsException e) { e.printStackTrace(); } catch (InvalidIdentifierException e) { e.printStackTrace(); } } reader.close(); } //...
} </java5>
Excepções não relacionadas com a função actual são simplesmente enviadas para o chamador.
<java5> class Network {
//... void registerFromFields(String[] fields) throws UnknownDataException, PublicationExistsException, UnknownAgentException, ClientExistsException, InvalidIdentifierException { // Regular expression pattern to match an agent. Pattern patAgent = Pattern.compile("^(PERSON|ORGANIZATION)"); // Regular expression pattern to match a message. Pattern patMessage = Pattern.compile("^(MESSAGE)"); // Regular expression pattern to match a publication. Pattern parPublication = Pattern.compile("^(IMAGE|NOTE|URI)"); // Regular expression pattern to match a publication. Pattern parConnection = Pattern.compile("^(CONNECTION)");
if (patAgent.matcher(fields[0]).matches()) { registerAgent(fields); } else if (patMessage.matcher(fields[0]).matches()) { registerMessage(fields); } else if (parPublication.matcher(fields[0]).matches()) { registerPublication(fields); } else if (parConnection.matcher(fields[0]).matches()) { registerConnection(fields); } else { throw new UnknownDataException(fields[0]); } } //...
} </java5>
Os campos relevantes (fields) são: 0 - type; 1 - id/null; 2 - agent; other - pub-specific
Excepções não relacionadas com a função actual são simplesmente enviadas para o chamador.
<java5> class Network {
//... void registerPublication(String... fields) throws PublicationExistsException, UnknownAgentException, UnknownDataException { int pubId = (fields[1] != null) ? Integer.parseInt(fields[1]) : getUUID(); int agtId = Integer.parseInt(fields[2]); if (fields[0].equals("IMAGE")) { Image image = new Image(pubId, fields[3], fields[4]); Agent owner = fetchAgent(agtId); owner.addPublication(pubId, image); setLastUUID(pubId); changed(); } else if (fields[0].equals("NOTE")) { TextNote note = new TextNote(pubId, fields[3], fields[4]); Agent owner = fetchAgent(agtId); owner.addPublication(pubId, note); setLastUUID(pubId); changed(); } else if (fields[0].equals("URI")) { URI uri = new URI(pubId, fields[3], fields[4]); Agent owner = fetchAgent(agtId); owner.addPublication(pubId, uri); setLastUUID(pubId); changed(); } else { throw new UnknownDataException(fields[0]); } } //...
} </java5>
Os campos relevantes (fields) são: type|id-or-null|name|email|phone
Excepções não relacionadas com a função actual são simplesmente enviadas para o chamador.
<java5> class Network {
//... void registerAgent(String... fields) throws ClientExistsException, UnknownDataException { int id = (fields[1] != null) ? Integer.parseInt(fields[1]) : getUUID(); if (fields[0].equals("PERSON")) { Person person = new Person(id, fields[2], fields[3], fields[4]); addAgent(id, person); setLastUUID(id); changed(); } else if (fields[0].equals("ORGANIZATION")) { Organization organization = new Organization(id, fields[2], fields[3], fields[4]); addAgent(id, organization); setLastUUID(id); changed(); } else { throw new UnknownDataException(fields[0]); } } //...
} </java5>
Os campos relevantes (fields) são:
Excepções não relacionadas com a função actual são simplesmente enviadas para o chamador.
<java5> class Network {
//... void registerMessage(String... fields) throws UnknownAgentException, UnknownDataException, InvalidIdentifierException { if (fields[0].equals("MESSAGE")) { int msgId = Integer.parseInt(fields[1]); Sender sender = fetchAgent(Integer.parseInt(fields[2])); List<Recipient> recipients = new ArrayList<Recipient>(); for (String recipientId : fields[3].split(",")) { Recipient recipient = fetchAgent(Integer.parseInt(recipientId)); recipients.add(recipient); } assertValidIdentifier(msgId); EmailMessage message = new EmailMessage(msgId, fields[2], sender, fields[3], recipients, fields[4], fields[5], "", null); sendMessage(message); setLastUUID(msgId); changed(); } else { throw new UnknownDataException(fields[0]); } } //...
} </java5>
Os campos relevantes (fields) são:
Excepções não relacionadas com a função actual são simplesmente enviadas para o chamador.
<java5> class Network {
//... void registerConnection(String[] fields) throws NumberFormatException, UnknownAgentException, UnknownDataException { if (fields[0].equals("CONNECTION")) { Agent a1 = fetchAgent(Integer.parseInt(fields[1])); Agent a2 = fetchAgent(Integer.parseInt(fields[2])); boolean a1Accepting = (Integer.parseInt(fields[3]) != 0); boolean a2Accepting = (Integer.parseInt(fields[4]) != 0); a1.addConnection(new Connection(a1, a2, a1Accepting, a2Accepting)); a2.addConnection(new Connection(a2, a1, a2Accepting, a1Accepting)); changed(); } else { throw new UnknownDataException(fields[0]); } } //...
} </java5>
Neste caso, apresenta-se a criação dinâmica de objectos de um determinado tipo, a partir de descrições textuais desses objectos.
Este exemplo utiliza informação de tipos em tempo de execução. Note-se que este tipo de abordagem apenas é possível em linguagens que providenciem este tipo de informação em tempo de execução, como é o caso do Java.