Instance One
today you come to work as usual and start your programming work as always.
The project manager tells you that today you want to add a new feature to the server, and you want to write a method that handles the book object, wrapping all the fields of the book object in XML format so that you can easily interact with the client later. and print the log before and after the start of the package so that it is convenient to debug and problem-Orient.
No problem! You think this function is a piece of cake, very confidently began to write code.
The book object code is as follows:
Class book
Attr_accessor:book_name,:p ages,:p Rice,: Author, ISBN end
Then write a class that is designed to wrap the book object in XML format:
Class Formatter
def format_book (book)
puts ' format begins ' result
= ' <book_name>#{book.book_name} </book_name>\n "Result
+ +" <pages>#{book.pages}</pages>\n "result
+ =" <price>#{ Book.price}</price>\n "Result
+ +" <author>#{book.author}</author>\n "result
+ +" < isbn>#{book.isbn}</isbn>\n "
puts" format finished "result End"
The calling code is as follows:
Book = book.new
book.book_name = "Programming Ruby"
book.pages = 830 Book.price = \ book.author =
"Dave T Homas "
book.isbn =" 9787121038150 "
formatter = formatter.new result
= Formatter.format_book (book)
Puts result
After you've written it, you can't wait to start running and the results are exactly what you expected.
The project manager after reading, is very satisfied with you, the boy efficiency is very high! You are also very proud.
However, two days later, the project manager found you, he said before the need to consider the interaction of the client also includes mobile devices, and mobile devices are compared to eat traffic, in XML format to transmit too much traffic, think the best to change to use the JSON format transmission. However, the previous XML format should also be preserved, preferably by the client specifying which format to use.
You are a little unhappy, in the mind underestimate, why not at the beginning of the comprehensive, and now to change the legacy code. But the other party is the leader, you still have to obey the order, so you start to modify the formatter class:
Class Formatter
def format_book (book, format)
puts "format begins" Result
= ""
if format = =: xml
result = "<book_name>#{book.book_name}</book_name>\n" result
+ = "<pages>#{book.pages}</ Pages>\n "Result
+ +" <price>#{book.price}</price>\n "result
+ =" <author>#{book.author }</author>\n "result + +
" <isbn>#{book.isbn}</isbn>\n "
elsif format = =: JSON result
+ = "{\ n" result
= = "\ book_name\": \ "#{book.book_name}\", \ n "Result
= =" "pages\": \ "#{book.pages}\", \ n " Result
= "\" price\ ": \" #{book.price}\ ", \ n" Result
= = "" author\ ": \" #{book.author}\ ", \ n" Result
= = "\ "isbn\": \ "#{book.isbn}\", \ n "result
+ ="} ' end
puts ' format
finished
The calling code is as follows:
Book = book.new
book.book_name = "Programming Ruby"
book.pages = 830 Book.price = \ book.author =
"Dave T Homas "
book.isbn =" 9787121038150 "
formatter = formatter.new result
= Formatter.format_book (book,: XML)
puts result
= Formatter.format_book (book,: JSON)
puts result
Run the program again and get the following results.
When the project manager sees the results, he says happily: "That's great, that's what I want!" ”
But you are not so happy this time, you think the code is a bit confusing, XML format logic and JSON format logic together, very bad for reading, and if you need to extend the functionality will be very difficult. Fortunately, the transfer format is also XML and JSON, there should be no extension, you can comfort yourself.
But fantasy will always be broken by reality, "I recently heard that there is a Yaml format is very fun ..." said the project manager. This time you've got the urge to hit someone,!!!.
Most of the time, the code written in the company is messy, the quality is very poor, a large part of the reason is because of the change in demand. We continue to supplement the various subsequent additions based on the original code, and our code becomes unsightly under the new if statement line. Of course, as programmers, we don't have much of a say in demand, and there's nothing we can do about it. But we can do our best to design the architecture of the program, let us write the code more extensibility, so that we can deal with a variety of requirements changes.
Below you will use the template method in 23 design patterns to improve the above program.
The first step is to define the specific subclass to handle each transmission format, so that the logic of the different transmission formats can be separated from one method, which is obviously easy to read and understand.
The definition class Xmlformatter inherits from formatter, which adds specific logic to handle XML formats:
Class Xmlformatter < Formatter
def formating (book) Result
= "<book_name>#{book.book_name}</book_ Name>\n "Result
+ +" <pages>#{book.pages}</pages>\n "result
+ +" <price>#{book.price} </price>\n "Result
+ +" <author>#{book.author}</author>\n "result
+ =" <isbn>#{ book.isbn}</isbn>\n "End"
The definition class Jsonformatter inherits from formatter, which adds specific logic to handle the JSON format:
Class Jsonformatter < Formatter
def formating (book) Result
= "{\ n" result =
"\ book_name\": \ "#{ Book.book_name}\ ", \ n" Result
= = "\" pages\ ": \" #{book.pages}\ ", \ n" Result
= = "" price\ ": \" #{book.price}\ ", \ n "Result
= =" \ "author\": \ "#{book.author}\", \ n "Result
= =" \ "isbn\": \ "#{book.isbn}\", \ n "Result
= = '} '
end End
The code in formatter is then modified as follows:
Class Formatter
def format_book (book)
before_format result
= formating (book)
After_format
result
-def before_format
puts "format begins"
End
def formating (book)
Raise "You should override this method in subclass."
End
def after_format
puts ' format finished '
end
You will find that the Format_book method is only four steps, and the first step is to call Before_format to print the log before the format conversion. The second step calls formating to handle the specific conversion logic, but the Formating method only raise an exception, because the logic of the specific transformation should be handled by subclasses, and if you go to the formating method of the parent class, you should see an exception. The third step calls After_format to print the converted log of the format. Step fourth returns result.
The final calling code is as follows:
Book = book.new
book.book_name = "Programming Ruby"
book.pages = 830 Book.price = \ book.author =
"Dave T Homas "
book.isbn =" 9787121038150 "
xmlformatter = xmlformatter.new result
= Xmlformatter.format_book ( Book)
puts result
Jsonformatter = jsonformatter.new result
= Jsonformatter.format_book (book)
puts Result
After running, you will find that the results of the run are identical to the results of the code before the modification. But after using the template method, the readability of the code has been greatly improved because the code that handles the format conversion is placed in its own class, rather than all of it in one method. And there has been a great increase in scalability, for example, you start to be interested in the YAML format that the project manager says.
The definition class Yamlformatter inherits from formatter, which adds specific logic to handle the YAML format:
Class Yamlformatter < Formatter
def formating (book) Result
= "Book_name: #{book.book_name}\n" result = =
"Pages: #{book.pages}\n" result
+ = "Price: #{book.price}\n" Result
= "Author: #{book.author}\n" result
+ = "ISBN: #{book.isbn}\n"
End
The calling code only needs to join:
Yamlformatter = yamlformatter.new Result
= Yamlformatter.format_book (book)
puts result
Well, the headaches of the YAML format is supported, only to decide when the call is instantiated xmlformatter,jsonformatter or Yamlformatter, you can follow the corresponding specifications for format conversion. And the overall code is very organized and looks very comfortable. At this time, you will easily to the project manager to ridicule a sentence, there is a need to support the format?
Example Two
Demand:
Students copy the topic, do the topic
Initial code
#-*-Encoding:utf-8-*-#学生甲的试卷类 class Testpapera def Question1 puts ' Yang passed, and later gave Guo Jing, smelting into the Sky Sword, Dragon Sword of the Xuan Iron may be [] a. Ductile iron B. tinplate C. High-speed alloy steel d. Carbon-plastic fiber ' puts ' answer: B ' End def Question2 puts ' Yang, Chengying, Lu Wu-Wu to eradicate the love flower, resulting in [] a. Make this plant harmless. B. Destroy the ecological balance of the biosphere. D. The answer to the "puts" of desertification in the area: A ' end def Question3 puts ' Blue Phoenix's cause Huashan Apprentice, Peach Valley six cents vomit more than, if you are a doctor, will give them prescribe what medicine [] A. Aspirin B-Bezoar jiedu tablets C. Fluoride d. Make them drink big. Quantity of raw milk e. Above all wrong ' puts ' answer: C ' End #学生乙的试卷类 class Testpaperb def Question1 puts ' Yang passed, and later gave the Guo Jing, refining into a day sword, Dragon Sword of the Xuan Iron may be [] a. Ductile Iron B. tinplate c. High-speed alloy steel D. Carbon fiber ' puts ' answer: d ' End def Question2 puts ' Yang, Chengying, Lu Wu-Wu to eradicate the love flower, resulting in [] a. Make this plant harmless B. Make a rare species extinct C. destroyed the The ecological balance of the biosphere D. Causing desertification in the area ' puts ' answer: B ' End def Question3 puts ' Blue Phoenix's cause Huashan Apprentice, Peach Valley six cents vomit more than, if you are a doctor, will give them to prescribe what medicine [] A. Aspirin B-Bezoar jiedu tablets C . Fluorine acid D. Let them drink a lot of raw milk e. Above all wrong ' puts ' answer: A ' end end puts ' student a copy of the paper ' Student1 = testpapera.new student1.question1 student1.que
Stion2 Student1.question3 puts ' student b copy of the paper ' Student2 = testpaperb.new student2.question1 student2.question2
Student2.question3
The problems that exist:
Testpapera and Testpaperb code in many of the same place, is not conducive to maintenance, if you need to modify the subject, it is necessary to change two places
The code after the change
#-*-Encoding:utf-8-*-class Testpaper def Question1 puts ' Yang got it, and later gave it to Guo Jing, the Sword of Heaven, and the Dragon Slayer. The Xuan iron may be [] a. Ductile iron B. tinplate c. High-speed alloy steel d. Carbon-plastic fiber ' end def Question2 puts ' Yang, Chengying, Lu Wu-Wu to eradicate the love flower, resulting in [] a. Make this plant harmless B. To destroy a rare species. C. destroyed the creature. The ecological balance of the circle D. resulting in desertification in the region ' end def Question3 puts ' Blue Phoenix's cause Huashan master and apprentice, Peach Valley six cents vomit more than, if you are a doctor, will prescribe to them what medicine [] A. Aspirin B-Bezoar jiedu tablets C. Fluoride d. Let them drink a lot of raw milk E
. None of the above is all right ' end #学生甲的试卷类 class Testpapera < Testpaper def Question1 Super puts ' answer: B ' End def Question2 Super puts ' answer: A ' End def Question3 Super puts ' answer: C ' End #学生乙的试卷类 class Testpaperb < Testpaper def Question1 Super puts ' answer: d ' End def Question2 Super puts ' answer: B ' End def Question3 Super puts ' answer: a ' E
nd end puts ' student a copy of the paper ' Student1 = testpapera.new student1.question1 student1.question2 student1.question3 ' student b copy of the paper ' Student2 = testpaperb.new student2.question1 student2.question2 student2.question3
The
can be seen, extracted out of a public test class, let a B to inherit, the common one of the questions. Then look at Testpapera and Testpaperb, the difference is only the answer a, B, C, D is not the same, the others are the same.
#-*-Encoding:utf-8-*-class Testpaper def Question1 puts ' Yang got it, and later gave it to Guo Jing, the Sword of Heaven, and the Dragon Slayer. The Xuan iron may be [] a. Ductile iron B. tinplate c. High-speed alloy steel D. Carbon fiber ' puts ' answer: #{answer1} "end def Question2 puts ' Yang, Chengying, Lu Wu-Wu to eradicate the love flower, resulting in [] a. Make this plant no longer harmful Man B. The extinction of a rare species C. Destroys the ecological balance of that biosphere. D. Causing desertification in the area ' puts ' answer: #{answer2} "end def Question3 puts ' Blue Phoenix's cause Huashan master and apprentice, Peach Valley six cents vomit more than, if you are a doctor , what drugs would they prescribe [] a. Aspirin B-Bezoar jiedu tablets C. Fluoride d. Let them drink a lot of raw milk e. The above all is not ' puts ' answer: #{answer3} "End Def Answer1; End Def Answer2; End Def Answer3;
End #学生甲的试卷类 Class Testpapera < Testpaper def Answer1 ' B ' End def Answer2 ' A ' "End def Answer3 ' C ' End #学生乙的试卷类 Class Testpaperb < Testpaper def Answer1 ' d ' End def Answer2 ' B ' End def Answer3 ' A ' end puts ' student a copy of the paper ' Student1 = testpapera.new student1.question1 student1.question2 student1.question3 ' student B copy Quiz paper ' Student2 = testpaperb.new student2.question1 student2.question2 student2.question3
Here, the answers in Testpapera and Testpaperb are drawn from the parent class to save only the different parts.
The parent class becomes the template for the subclass, and all duplicated code should go up to the parent class instead of having to repeat each subclass.
When we want to complete a process or a series of steps that are consistent at a level of detail, but the implementation of individual steps at a more detailed level may not be the same, we usually consider using template method patterns for processing.