GoF design patterns are also hidden in the Java libraries that you use most often. It's easy to overlook the busy daily work, but once in a while, let's take a closer look at the beautiful design, which can be said to be a kind of art.
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Text;
...
...
//Generate new XML document in memory
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.newDocument();
//Generate XML elements
Element element = document.createElement("element");
Text text = document.createTextNode("text");
Attr attribute = document.createAttribute("attribute");
...
It's a scene where XML documents and elements are generated in Java, but when I watch it again, I find myself in a profound and mysterious interface.
Instead of creating a new XML Document
instance directly, I'm going through the DocumentBuilderFactory
and DocumentBuilder
classes. It is an interface of 3 consecutive newXXX
reminiscent of Dom's jet stream attack (attack by Dom's pilot trio) [^ 1] that afflicted Gundam with Mobile Suit Gundam, but honestly, redundancy is noticeable. , Doesn't look very beautiful. However, if you read the source code hidden behind it, you may feel something. Let's explore the feelings of the designer together.
Let's start by generating XML documents and elements with the most intuitive code. Please note that the source code for this section contains fictitious classes for illustration purposes.
Factory pattern
//Document corresponds to the Factory class of the element
Document document = new Document();
//Generate XML elements
XMLElement element = document.createXMLElement("element");
XMLText text = document.createXMLTextNode("text");
XMLAttr attribute = document.createXMLAttribute("attribute");
...
There is no particular problem for this purpose only. Now, let's make it possible to generate SOAP [^ 2] elements in addition to XML elements.
Continuation of Factory pattern
//Create SOAP element
SOAPElement element = document.createSOAPElement("element");
SOAPText text = document.createSOAPTextNode("text");
SOAPAttr attribute = document.createSOAPAttribute("attribute");
...
Then, there will be more createXXX ...
variations, such as createSOAP ...
. It's not beautiful to have to add a lot of createXXX ...
methods to an existing class (Document
) just by adding one more document type such as XML / SOAP.
Now let's apply the Abstract Factory pattern. The first is the generation of the XML document.
AbstractFactory pattern (Factory)
//When generating an XML document (Document is equivalent to Factory class)
Document document = new XMLDocument(); //Document subclass
Generate the SOAP document as follows.
AbstractFactory pattern (Factory)
//When generating a SOAP document (Document is equivalent to Factory class)
Document document = new SOAPDocument(); //Document subclass
In either case, the element is generated as follows.
AbstractFactory pattern (things generated by Factory)
//Generate element
Element element = document.createElement("element");
Text text = document.createTextNode("text");
Attr attribute = document.createAttribute("attribute");
Inherit the Document
class that corresponds to the abstracted Factory, and create the XMLDocument
and SOAPDocument
classes that correspond to the concrete Factory. (This class is fictitious.) Then, even if you increase the types of documents such as XML / SOAP, you no longer need to add the createXXX ...
method. At the same time, the things generated by Factory (ʻElement,
Text, ʻAttr
, etc.) are also abstracted, so they can be treated in the same way regardless of the type of element such as XMLElement
/ SOAPElement
. I will. It's simple and beautiful.
The GoF definition of the Abstract Factory pattern is "provides an interface that creates a family of related or dependent objects without specifying their concrete class [^ 3]". The "family of related or dependent objects" here corresponds to ʻElement,
Text, and ʻAttr
. Also, "an interface generated without specifying its concrete class" is equivalent to Document
.
The Abstarct Factory pattern is very simple as mentioned above, but it is often thought to be "difficult". When I was in my first and second year as an engineer, I wasn't quite sure. (Okay, that [Hiroshi Yuki](https://www.amazon.co.jp/%E7%B5%90%E5%9F%8E-%E6%B5%A9/e/B003UW60OA/ref=pd_sim_14_bl_1? _encoding = UTF8 & refRID = YDTDY91X8NYH1QKXNTMF) It is the pattern that I found to be the most difficult.) The reason why I find it difficult is that there are many classes that appear, but more than that, ** it is hard to understand what I am happy with * * I think it is there.
To be honest, in the above example, WEB of the introduction to design patterns, and the example of books, even if you use the Abstract Factory pattern, you are not so happy. There is none. In these, the program is simplified to make the essence of the pattern easier to understand, but the actual benefits of the Abstract Factory pattern are when the program is somewhat complex.
In conclusion, I think the best scene to benefit from the Abstract Factory pattern is when you want to hide the generation of the abstract Factory class.
The figure is as follows. "Minimum usage" and "How to show your true potential".
AbstractFactory (minimum usage)
|Caller|
↓ ↓
↓ Use ↓ Select Factory to generate
↓ ↓
↓ |Abstract Factory|
↓ |Specific Factory to inherit|
↓ ↓
↓ ↓ Generate
↓ ↓
|Things made with Factory|
AbstractFactory (how to show its true character)
|Caller|
↓ ↓
↓ Use ↓ Use
↓ ↓
↓ |Abstract Factory|
↓ ↓
↓ ↓ Select Factory to generate
↓ ↓
↓ |Specific Factory|
↓ ↓
↓ ↓ Generate
↓ ↓
|Things made with Factory|
The "select and generate Factory" part is different between "minimum usage" and "how to demonstrate its true potential". At a minimum, the caller determines the implementation class of the abstracted Factory. On the other hand, in the real world, the abstracted Factory class uses dynamic class loading [^ 4] and a configuration file to determine the Factory implementation class. Therefore, the caller can replace the concrete Factory implementation class without changing the source code.
Now let's take a look at the code at the beginning of the page again.
//Generate Document corresponding to Element Factory class
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.newDocument();
//Generate element
Element element = document.createElement("element");
Text text = document.createTextNode("text");
Attr attribute = document.createAttribute("attribute");
DocumentBuilderFactory
is equivalent to the" Abstract Factory "of the Abstract Factory pattern. The newInstance
method creates a" concrete Factory "that is a subclass of this DocumentBuilderFactory
. You can choose the specific Factory implementation class from the following vendors.
These implementation classes are automatically found in the newInstance
method of DocumentBuilderFactory
in the following order:
lib / jaxp.properties
file in the JRE directoryMETA-INF / services / javax.xml.parsers.DocumentBuilderFactory
file in the jar file (Java ServiceLoader mechanism is used)com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl
)Therefore, ** changing the implementation class does not require any changes to the calling code **. I cannot help feeling the artistry of this mechanism.
In addition, two Abstract Factory patterns are hidden in the code at the beginning [^ 5]. Each has the following configuration. (For the word Factory, the thing made by Factory is expressed as Product.)
Many experts have also commented on the Abstract Factory pattern.
Alan Shalloway, James R. Trot
For example, if you are developing a user interface for a system that runs on multiple platforms, you will be using a set of interface objects prepared for each OS you are using. In this way, you can use the Abstract Factory pattern to use different objects depending on the situation.
["Object-oriented mind"](https://www.amazon.co.jp/%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82 % AF% E3% 83% 88% E6% 8C% 87% E5% 90% 91% E3% 81% AE% E3% 81% 93% E3% 81% 93% E3% 82% 8D-SOFTWARE-PATTERNS-% E3% 82% A2% E3% 83% A9% E3% 83% B3-% E3% 82% B7% E3% 83% A3% E3% 83% AD% E3% 82% A6% E3% 82% A7% E3 From% 82% A4 / dp / 4621066048 /)
Jiggs Co., Ltd.
There is a "Factory Method" pattern that is very similar, but the "Factory Method" pattern is a pattern that focuses on the abstraction of "object generation", while the "Abstract Factory" pattern is "related". It is in the abstraction of "Procedures for collectively generating a group of objects to be used".
From IT Senka-Introduction to Design Patterns> Abstract Factory Patterns
It's the real pleasure of programmers to be able to enjoy intellectual enjoyment by just looking at a few lines of code without having to go to the museum.
If you are an engineer who sympathizes with the artistry of the Abstract Factory pattern, please contact the recruiting staff of our company (Qualysite Technologies Inc.). Please contact me!
-Design pattern to enjoy with Java library used frequently --Factory pattern -Design patterns to enjoy with frequently used Java libraries --Builder patterns --Design patterns that you can enjoy with your favorite Java library --Abstract Factory pattern
-Design patterns to enjoy with Java libraries that are often used --Facade patterns -Design pattern to enjoy with frequently used Java library --Adapter pattern
-Design patterns to enjoy with frequently used Java libraries --Template Method patterns -Design patterns to enjoy with frequently used Java libraries --Strategy patterns
[^ 1]: [Black Tertiary Star-Wikipedia](https://ja.wikipedia.org/wiki/Black Tertiary Star)
[^ 2]: Protocol for communicating with XML. Used on HTTP.
[^ 3]: ["Design pattern for reuse in object orientation"](https://www.amazon.co.jp/%E3%82%AA%E3%83%96%E3%82%B8 % E3% 82% A7% E3% 82% AF% E3% 83% 88% E6% 8C% 87% E5% 90% 91% E3% 81% AB% E3% 81% 8A% E3% 81% 91% E3 % 82% 8B% E5% 86% 8D% E5% 88% A9% E7% 94% A8% E3% 81% AE% E3% 81% 9F% E3% 82% 81% E3% 81% AE% E3% 83 % 87% E3% 82% B6% E3% 82% A4% E3% 83% B3% E3% 83% 91% E3% 82% BF% E3% 83% BC% E3% 83% B3-% E3% 82% AC% E3% 83% B3% E3% 83% 9E-% E3% 82% A8% E3% 83% AA% E3% 83% 83% E3% 82% AF / dp / 479731126 / ref = sr_1_1? Ie = UTF8 & qid = 1495503419 & sr = 8-1 & keywords =% E3% 82% AA% E3% 83% 96% E3% 82% B8% E3% 82% A7% E3% 82% AF% E3% 83% 88% E6% 8C% 87% E5% 90% 91% E3% 81% AB% E3% 81% 8A% E3% 81% 91% E3% 82% 8B% E5% 86% 8D% E5% 88% A9% E7% 94% A8% E3% 81% AE% E3% 81% 9F% E3% 82% 81% E3% 81% AE% E3% 83% 87% E3% 82% B6% E3% 82% A4% E3% 83% B3% E3% 83% From 91% E3% 82% BF% E3% 83% BC% E3% 83% B3)
[^ 4]: I wrote it in parentheses, but it's just the Java standard ClassLoader Is a method of creating an instance from a package name and class name that are hard-coded as strings in the source code using.
[^ 5]: Strictly speaking, the first Abstract Factory is not the Abstract Factory pattern defined in GoF because there is only one type of abstracted Product, DocumentBuilder
.
Recommended Posts