Thinking in Patterns with Java V0.9: chapter 19: Pattern refactoring:
TIPatterns.htm#_Toc41169793
1, Sections:
Pattern refactoring 181
Simulating the trash recycler. 182
Improving the design. 186
?Make more objects?. 186
A pattern for prototyping creation 189
Trash subclasses. 193
Parsing Trash from an external file 195
Recycling with prototyping. 198
Abstracting usage. 199
Multiple dispatching. 203
Implementing the double dispatch 204
The Visitor pattern. 211
A Reflective Decorator. 214
More coupling?. 219
RTTI considered harmful?. 220
Summary. 223
Exercises. 224
2, The main content and feeling:
This chapter foucuses on the applying of some patterns in the before chapters. With a trash recyleing system example, step by step, in an evoluting style, the book teachs me how to refine a system with design patterns by asking an important question in this processing: "what will change?" continuely.
The summary of this chapter is also the summary of design patterns given by the author. So, it worth to be read regularly later.
Here is some words about this summary:
1), "Design patterns in general strive to separate the things that change from the things that stay the same."
2), Finding the "vector of change" can be happened at any stage of a system's life. So, refining system may be happened through a system's life.
3), "What design patterns say is that OOP isn't just about polymorphism. It's about 'separating the things that change from the things that stay the same.'"
"But design patterns in general show other ways to accomplish the basic goal, and once your eyes have been opened to this you will begin to search for more creative designs."
4), Now, I make a review of how to refine a first-cut system step by step with design patterns in this book's trash recycling system.
(1), After the first-cut of "Simulating the trash recycler", the question to be raised:"What if the situation changes", for example, a new type trash called cardboard to be added into system, this will cause code less maintainable.
(2), So, "The solutions in Design Patterns are organized around the question
?What will change as this program evolves?? This is usually the most important
question that you can ask about any design. If you can build your system around
the answer, the results will be two-pronged: not only will your system allow
easy (and inexpensive) maintenance, but you might also produce components that
are reusable, so that other systems can be built more cheaply. "
"This brings up a general object-oriented design principle that I
first heard spoken by Grady Booch: 'If the design is too complicated, make more
objects.' "
Then a Messenger class to be created to encapsulate trash information, just the Messenger Pattern to be used here.
Then, the Factory Pattern to be used by "the only code that must be modified is within the factory, so the factory isolates the effect of that change."
For a more flexiable adding new trash type, the Prototype Pattern which hasn't been described in the previous chapters appears, it is just "The general idea is that you have a master sequence of objects, one of
each type you?re interested in making. The objects in this sequence are used
only for making new objects, using an operation that?s not unlike the clone( )
scheme built into Java?s root class Object. In this case, we?ll name the
cloning method tClone( ). When you?re ready to make a new object, presumably
you have some sort of information that establishes the type of object you want
to create, then you move through the master sequence comparing your information
with whatever appropriate information is in the prototype objects in the master
sequence. When you find one that matches your needs, you clone it."
But, in this example, the "master sequence of objects" doesn't hold "objects", they are Classes. And, with Java 1.1 reflection, these Class objects can be used to create the real object of that Class. Maybe, I have misunderstood "Prototype Pattern.
(3), But, "In terms of object creation, this design does indeed severely
localize the changes you need to make to add a new type to the system. However,
there?s a significant problem in the use of RTTI that shows up clearly here.
The program seems to run fine, and yet it never detects any cardboard, even
though there is cardboard in the list! This happens because of the use of RTTI,
which looks for only the types that you tell it to look for. The clue that RTTI
is being misused is that every type in the system is being tested, rather than
a single type or subset of types. As you will see later, there are ways to use
polymorphism instead when you?re testing for every type."
Because "RTTI is being misused", so we need step furthermore "So it?s worth trying to eliminate RTTI in this case, not just for aesthetic reasons?it produces more maintainable code."
(4), In the new implemetion of trash recyleing system: //: refactor:recycleb:RecycleB.java, "Adding new types to the system consists of adding or modifying distinct classes without causing code changes to be propagated throughout the system."
But, a further challenge be posted, RTTI "it should be eliminated altogether from the operation of sorting the trash into bins." I think to say it is because: "if(t.getClass().equals(type))" in the the code below:
public boolean grab(Trash t) {
// Comparing class types:
if(t.getClass().equals(type)) {
list.add(t);
return true; // Object grabbed
}
return false; // Object not grabbed
}
|
|
This code locates in //: refactor:recycleb:RecycleB.java.
Its meaning is "t.getClass()" is also a kind of RTTI?
(5), So, the multiple dispatching to be used to "end up detecting some types manually and effectively producing your own dynamic
binding behavior" with "the polymorphism (dynamically-bound method calls) is to handle type-specific information for you."
Look at the code below, the multiple dispatching is used like this:
For trash:
interface TypedBinMember {
// The new method:
boolean addToBin(TypedBin[] tb);
} ///:~
|
|
For bin:
public abstract class TypedBin {
Collection c = new ArrayList();
protected boolean addIt(Trash t) {
c.add(t);
return true;
}
public Iterator iterator() {
return c.iterator();
}
public boolean add(DDAluminum a) {
return false;
}
public boolean add(DDPaper a) {
return false;
}
...
}
|
|
(6), "While previous versions of the trash sorting
example emphasized the addition of new types of Trash to the system,
TrashVisitor.java allows you to easily add new functionality without disturbing
the Trash hierarchy. There?s more code in TrashVisitor.java, but adding new
functionality to Visitor is cheap. If this is something that happens a lot,
then it?s worth the extra effort and code to make it happen more easily."
Here, the Vistor Pattern to be used for the reason above which be described in the summary of this chapter.
(7), Here, author tells me don't chase "Low coupling and high cohesion" too much :"Applied mindlessly, though, it can prevent you from achieving a more elegant design. It seems that some classes inevitably have a certain intimacy with each other. These often occur in pairs that could perhaps be called couplets;"
(8), At last, author tells me:"However, RTTI doesn?t automatically create non-extensible code. "
With right-use of "RTTI", //: refactor:dynatrash:DynaTrash.java
// Using a Map of Lists and RTTI to automatically sort
// trash into ArrayLists. This solution, despite the
// use of RTTI, is extensible.
And, it also is a beautiful design to use "a new tool will be introduced, which I call a TypeMap.", "This is certainly the smallest solution to the problem, and arguably the most elegant as well. It does rely heavily on RTTI,...".
It seems to tell me, with the good design, you can use almost any tool(technique) to build you system.
3, Questions about programming:
1), return (Trash)ctor.newInstance(
new Object[]{new Double(info.data)});
The process of calling
newInstance( ) extracts the double, but you can see it is a bit confusing?an
argument might be a double or a Double, but when you make the call you must
always pass in a Double. Fortunately, this issue exists only for the primitive
types.
2),
public class Cardboard extends Trash {
private static double val = 0.23f;
public Cardboard(double wt) { super(wt); }
public double getValue() { return val; }
public static void setValue(double newVal) {
val = newVal;
}
} ///:~
|
|
A question: Can I put the code except constructor in such sub-class like above
into their super class: Trash and don't re-write them in all the sub-classes?
My researching:
Why don't do like below:
public abstract class Trash {
private double value;
private double weight;
public Trash(double val, double wt) {
value = val;
weight = wt;
}
public double getValue() {
return value;
}
public double getWeight() {
return weight;
}
}
|
|
public class Cardboard extends Trash {
public Cardboard(double val, double wt) {
super(val, wt);
}
} ///:~
|
|
3),
//: refactor:doubledispatch:DDCardboard.java
// Cardboard for double dispatching.
package refactor.doubledispatch;
import refactor.trash.*;
public class DDCardboard extends Cardboard
implements TypedBinMember {
public DDCardboard(double wt) { super(wt); }
public boolean addToBin(TypedBin[] tb) {
for(int i = 0; i < tb.length; i++)
if(tb[i].add(this))
return true;
return false;
}
} ///:~
|
|
There is same code which be marked as red color in the above class as other classes like above, why don't put them into their base class?
There is an answer in the book:
But notice the argument: this. The type of this is different for each subclass of Trash, so the code is different.
|
|
But, I haven't understood very clearly, it needs more further learning for me.
4),
Of course, in this case it works well only if you’re adding new Visitors, but it gets in the way when you add new types of Trash.
4, Questions about english language:
1), Strange words:
bin, Aluminum, branch off, silly, turn around, receptacle, enigma, commodity,
cardboard, definitely, recycling, appropriate, the results will be two-pronged,
promise, insight, refinement, would like, This is simultaneously counterintuitive and ludicrously simple, indirection, accidental, elevate, elaborate, eliminate, for that matter, presumably, work with, drop out, rectify, facilitate, severely, aesthetic, clue, be aware of,strictly,satisfactory, purist, altogether, dilemma, have control of, ease, Reflective, albeit, tally, inevitable, intimacy, in pairs, couplets, condemnation, ill-fated, stated, counterproductive, strive, analyst, about-face, syndrome, prohibitively, fame, proponent, autonomous,
2), Strange sentences:
The extra constraint is that the trash arrives at the trash recycling plant all mixed together.
(Indeed, this is the whole enigma of recycling).
(we?ve started referring to Messenger as a design pattern, but it?s simple enough that you may not choose to elevate it to that status).
then you move through the master sequence comparing your information with whatever appropriate information is in the prototype objects in the master sequence.(whatever?)
If it still can?t be found something is really wrong, but if
the load is successful then the factory method is called recursively to try
again.
Note that the benefit is helpful here but not exactly what we started out to accomplish, so at first blush you might decide that this isn’t the desired solution.
incomplete