Reprinted please indicate the source: http://blog.csdn.net/guolin_blog/article/details/9153761
This is a copy version of Java Design Pattern dialysis, which is specially provided for Ruby lovers. If you are not familiar with Ruby syntax, please refer:
Java Design Pattern Analysis-Composite)
I heard that your company has recently launched a new E-book reading application. The market is very responsive. There are also book malls in the application, where users can choose their favorite books at will. Your company also attaches great importance to this project, increases investment, and decides to add more features to this application.
Well, you also know that you are not able to escape this attack. It wasn't long before your leader found you. He told you that the current application has made statistics on the page views and sales volume of each book, but now I want to increase the page views and sales volume of each book category, as well as the overall page views and sales volume of all books. I hope you can complete this function.
Of course, the jobs arranged by the leaders cannot be put off. You can only put your head on it, but fortunately this function does not look very complicated.
If you prefer novels, start with the statistical functions of novels. First, the get_all_novels method can be used to obtain all novel names, and then the novel name is passed into the get_browse_count method to obtain the book's page views. The new novel name is passed into the get_sale_count method to obtain the book's sales volume. You can only use these known APIs!
def get_novels_browse_countbrowse_count = 0all_novels = get_all_novels()all_novels.each do |novel|browse_count += get_browse_count(novel)endbrowse_countenddef get_novels_sale_countsale_count = 0all_novels = get_all_novels()all_novels.each do |novel|sale_count += get_browse_count(novel)endsale_countend
Soon you will write down the above two methods, both of which are obtained by getting all the novel names, then calculating the page views and sales volume of each novel one by one, and finally adding the results to get the total amount.
The novel statistics are complete, and then you start to do the statistical function of computer books, the Code is as follows:
def get_computer_books_browse_countbrowse_count = 0all_computer_books = get_all_computer_books()all_computer_books.each do |computer_book|browse_count += get_browse_count(computer_book)endbrowse_countenddef get_computer_books_sale_countsale_count = 0all_computer_books = get_all_computer_books()all_computer_books.each do |computer_book|sale_count += get_browse_count(computer_book)endsale_countend
Except that the get_all_computer_books method is used to obtain the names of all computer classes, other codes are basically the same as those in the novel statistics.
Now you have completed the statistical functions of two types of books, followed by books such as medicine, nature, history, law, politics, philosophy, tourism, and food. You suddenly realized the seriousness of some problems, and the heavy workload is nothing, but if you write it like this, your method will be exploding. So many methods can't be seen, don't mention how to use it.
At this time, you have to ask your leader for help and explain your confusion to him. I saw your leader think for a moment, and then confidently told you that using the combination mode not only can easily eliminate your confusion, but also achieve outstanding functionality.
He immediately showed you the encoding operation. First, he defined a statistics class, which has two methods:
class Statisticsdef get_browse_countraise "You should override this method in subclass."enddef get_sale_countraise "You should override this method in subclass."endend
Both methods simply throw an exception because the two methods need to be rewritten in the subclass.
Then define a novelstatistics class used to count novel books, inherit the just-defined statistics class, and override the two methods in statistics:
class NovelStatistics < Statisticsdef get_browse_countbrowse_count = 0all_novels = get_all_novels()all_novels.each do |novel|browse_count += get_browse_count(novel)endbrowse_countenddef get_sale_countsale_count = 0all_novels = get_all_novels()all_novels.each do |novel|sale_count += get_browse_count(novel)endsale_countendend
The two methods respectively calculate the page views and sales volume of novel books. In the same way, your leader defines a computerbookstatistics class to count the page views and sales volume of computer books:
class ComputerBookStatistics < Statisticsdef get_browse_countbrowse_count = 0all_computer_books = get_all_computer_books()all_computer_books.each do |computer_book|browse_count += get_browse_count(computer_book)endbrowse_countenddef get_sale_countsale_count = 0all_computer_books = get_all_computer_books()all_computer_books.each do |computer_book|sale_count += get_browse_count(computer_book)endsale_countendend
In this way, the specific statistical implementation will be dispersed in various classes, and there will be no more explosion in the method you just created. However, you have not started to use the combination mode yet, And your leader boasted that a good show is still coming soon.
Define a new maid class to inherit statistics, used to count the browsing volume and sales volume of medical books. The Code is as follows:
class MedicalBookStatistics < Statisticsdef get_browse_countbrowse_count = 0all_medical_books = get_all_medical_books()all_medical_books.each do |medical_book|browse_count += get_browse_count(medical_book)endbrowse_countenddef get_sale_countsale_count = 0all_medical_books = get_all_medical_books()all_medical_books.each do |medical_book|sale_count += get_browse_count(medical_book)endsale_countendend
I don't know if you have found out. Computer books and medical books are actually scientific books. They can be combined. At this time, your leader defines a technicalstatistics class for statistics on the combination of science and technology books:
class TechnicalStatistics < Statisticsdef initialize@statistics = []@statistics << ComputerBookStatistics.new@statistics << MedicalBookStatistics.newenddef get_browse_countbrowse_count = 0@statistics.each do |s|browse_count += s.get_browse_countendbrowse_countenddef get_sale_countsale_count = 0@statistics.each do |s|sale_count += s.get_sale_countendsale_countendend
As you can see, because this class is a combination class, it is quite different from the previous classes. First, technicalstatistics has a constructor. In the constructor, computer books and medical books are added to the statistics array as subcategories, and then all subcategories are traversed in the get_browse_count and get_sale_count methods respectively, calculate their respective page views and sales volume, and then sum them to get the total value.
The combination mode has excellent scalability. There are no rules or rules, and you can combine them as you want. For example, all books are composed of different categories, your leader immediately showed off how to count the page views and sales volume of all books.
Defines an allstatistics class to inherit statistics. The specific code is as follows:
class AllStatistics < Statisticsdef initialize@statistics = []@statistics << NovelStatistics.new@statistics << TechnicalStatistics.newenddef get_browse_countbrowse_count = 0@statistics.each do |s|browse_count += s.get_browse_countendbrowse_countenddef get_sale_countsale_count = 0@statistics.each do |s|sale_count += s.get_sale_countendsale_countendend
In the allstatistics constructor, novel books and scientific books are added to the statistics array as subcategories. Currently, you have only written these categories. Use the same method to calculate the page views and sales volume of all books in the get_browse_count and get_sale_count methods.
The current combination structure is as follows:
Now you can easily get the page views and sales of any classified books. For example, to get the page views of Science and Technology Books, you only need to call:
TechnicalStatistics.new.get_browse_count
To obtain the total sales volume of all books, you only need to call:
AllStatistics.new.get_sale_count
Of course, you can also randomly change the combination structure, add books of various seed categories, and the hierarchy of sub-categories can be any deeper. As mentioned above, the combination mode is highly scalable.
Your leader tells you that the Code he has written has a high degree of repetition. In fact, you can optimize it and remove redundant code. Of course, this task will be handed over to you. Your leader is a busy man and has been running away for a long time.
Combination: Combine objects into a tree structure to represent the "part-whole" hierarchy. The combination mode ensures consistency between the use of a single object and a composite object.