definition:It is also called composite mode, or part whole mode. It is mainly used to describe the relationship between part and whole, define and combine objects into a tree structure to represent the hierarchical structure of “part whole”, so that users can use single objects and combined objects consistently.
Class diagram:
Role description:
Componnent abstract component role: define common methods and properties of objects participating in composition, and define some default behaviors or properties.
Leaf component: leaf object, under which there are no other branches, that is, the smallest unit of traversal.
Composite branch component: Branch object, which is used to combine branch nodes and leaf nodes to form a tree structure.
example:
I heard that your company has recently launched an e-book reading application, and the market response is very good. There is a Book Mall in the application, in which users can choose their favorite books at will. Your company also attaches great importance to this project, increases investment, and decides to add more functions to this application.
Well, you know you can’t escape this robbery. It wasn’t long before your leader found you. He told you that the current application makes statistics on the number of views and sales of each book, but now he wants to add the function of statistics on the number of views and sales of each book classification and the total number of views and sales of all books. I hope you can complete this function.
Of course, the work arranged by the leader can’t be shirked. You can only bite the bullet, but fortunately, this function doesn’t seem very complicated.
You prefer reading novels, so start with the statistical function of novels. First, get_ all_ The novels method can get all the novel names, and then pass the novel names into get_ browse_ The count method can get the number of views of the book and pass the novel name into get_ sale_ The count method can get the sales volume of the book. At present, you only have these known APIs to use, so start!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
def get_novels_browse_count browse_count = 0 all_novels = get_all_novels() all_novels. each do |novel| browse_count += get_browse_count(novel) end browse_count end def get_novels_sale_count sale_count = 0 all_novels = get_all_novels() all_novels. each do |novel| sale_count += get_browse_count(novel) end sale_count end |
Soon you wrote down the above two methods. Both methods get all the novel names, then calculate the views and sales of each novel one by one, and finally add the results to get the total amount.
The statistics of novels are completed, and then you start to do the statistics function of computer books. The code is as follows:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
def get_computer_books_browse_count browse_count = 0 all_computer_books = get_all_computer_books() all_computer_books. each do |computer_book| browse_count += get_browse_count(computer_book) end browse_count end def get_computer_books_sale_count sale_count = 0 all_computer_books = get_all_computer_books() all_computer_books. each do |computer_book| sale_count += get_browse_count(computer_book) end sale_count end |
In addition to using get_ all_ computer_ The books method obtains all computer book titles. 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 medical, natural, historical, legal, political, philosophical, tourism, food and so on. You suddenly realize the seriousness of some problems. A large workload is nothing, but if you continue to write like this, your methods will explode. So many methods can’t be seen. Don’t mention how to use them.
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 can not only easily eliminate your confusion, but also complete the function excellently.
He immediately showed you the coding operation. First, he defined a statistics class with two methods:
1
2
3
4
5
6
7
8
9
10
11
|
class Statistics def get_browse_count raise "You should override this method in subclass." end def get_sale_count raise "You should override this method in subclass." end end |
Both methods simply throw an exception because they need to be overridden in subclasses.
Then define a novelstatistics class for statistical novel books, inherit the statistics class just defined, and override the two methods in Statistics:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
class NovelStatistics < Statistics def get_browse_count browse_count = 0 all_novels = get_all_novels() all_novels. each do |novel| browse_count += get_browse_count(novel) end browse_count end def get_sale_count sale_count = 0 all_novels = get_all_novels() all_novels. each do |novel| sale_count += get_browse_count(novel) end sale_count end end |
In these two methods, the views and sales of novel books are counted respectively. In the same way, your leader defines a computerbookstatistics class to count the number of views and sales of computer books:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
class ComputerBookStatistics < Statistics def get_browse_count browse_count = 0 all_computer_books = get_all_computer_books() all_computer_books. each do |computer_book| browse_count += get_browse_count(computer_book) end browse_count end def get_sale_count sale_count = 0 all_computer_books = get_all_computer_books() all_computer_books. each do |computer_book| sale_count += get_browse_count(computer_book) end sale_count end end |
In this way, the specific statistical implementation will be scattered in various classes, and there will be no explosion of the method you just described. But it hasn’t really started using the combination mode yet. The good play is still ahead, your leader boasted.
Define a medicalbookstatistics class to inherit statistics, which is used to count the number of views and sales of medical books. The code is as follows:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
class MedicalBookStatistics < Statistics def get_browse_count browse_count = 0 all_medical_books = get_all_medical_books() all_medical_books. each do |medical_book| browse_count += get_browse_count(medical_book) end browse_count end def get_sale_count sale_count = 0 all_medical_books = get_all_medical_books() all_medical_books. each do |medical_book| sale_count += get_browse_count(medical_book) end sale_count end end |
I don’t know if you found it. Computer books and medical books are actually science and technology books. They can be combined together. At this time, your leader defines a technicalstatistics class to count the combined books of science and technology:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
class TechnicalStatistics < Statistics def initialize @statistics = [] @statistics << ComputerBookStatistics. new @statistics << MedicalBookStatistics. new end def get_browse_count browse_count = 0 @statistics . each do |s| browse_count += s.get_browse_count end browse_count end def get_sale_count sale_count = 0 @statistics . each do |s| sale_count += s.get_sale_count end sale_count end end |
You can see that because this class is a composite class, it is still quite different from the previous classes. Firstly, there is a constructor in technical statistics. In the constructor, computer books and medical books are added to the statistics array as subcategories, and then they are respectively added in get_ browse_ Count and get_ sale_ Count method traverses all sub categories, calculates their respective views and sales, and then adds them to get the total return.
The expansibility of the combination mode is very good. There are no rules and regulations. You can combine as you want. For example, all books are combined by various categories. Your leader immediately showed you the way to count the views and sales of all books.
Define an allstatistics class to inherit statistics. The specific code is as follows:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
class AllStatistics < Statistics def initialize @statistics = [] @statistics << NovelStatistics. new @statistics << TechnicalStatistics. new end def get_browse_count browse_count = 0 @statistics . each do |s| browse_count += s.get_browse_count end browse_count end def get_sale_count sale_count = 0 @statistics . each do |s| sale_count += s.get_sale_count end sale_count end end |
In the constructor of allstatistics, add novel books and science and technology books as sub categories to the statistics array. At present, you have only written these categories. Then use the same method in get_ browse_ Count and get_ sale_ Count method to count the number of views and sales of all books.
The schematic diagram of the current composite structure is as follows:
Now you can easily get the views and sales volume of any classified books. For example, to get the views of science and technology books, you only need to call:
1
|
TechnicalStatistics. new .get_browse_count |
To get the total sales of all books, you only need to call:
1
|
AllStatistics. new .get_sale_count |
Of course, you can also change the composition structure at will, add various sub classification books, and the sub classification hierarchy can be as deep as you want. As mentioned earlier, the scalability of the composition mode is very good.
Your leader tells you that the code he wrote is highly repetitive. In fact, it can be optimized to remove the redundant code. Of course, this task is left to you. Your leader is a busy man and has long run away.
summary
Advantages of combined mode:
It can flexibly combine the concerns between local objects and overall objects. For the client, there is no difference between the calls of local objects and overall objects, making the call simple.
Disadvantages of combination mode:
1. The cost of combination operation is very high. If there are many sub objects in an object tree, a simple call may crash the system;
2. The problem of object persistence. The composite schema is a tree structure, which can not store data well in the relational database, but it is very suitable for XML persistence.
Applicable scenarios of combination mode:
1. Maintenance and presentation part – scenarios of overall relationship, such as tree menu, file and folder management.
2. Scenarios that can separate some modules or functions from a whole.