Design pattern (structural type) combination mode (Composite pattern)

Source: Internet
Author: User

PS One sentence: Eventually choose Csdn to organize the publication of the knowledge points of these years, the article parallel migration to CSDN. Because CSDN also support markdown grammar, Ah!

"Craftsman Joshui Http://blog.csdn.net/yanbober" read the previous "bridge pattern" of design mode (structural type) http://blog.csdn.net/yanbober/article/ details/45366781

Overview

The combination pattern, also called part-whole mode, allows us to blur the concept of simple elements and complex elements in the tree structure, and the client program can deal with complex elements like simple elements, thus decoupling the client program from the internal structure of the complex elements. Combined mode optimizes the processing of recursive or hierarchical data structures. There are many examples of hierarchical data structures that make combinatorial patterns very useful.

Core

concept: combine multiple objects to form a tree structure to represent a hierarchy with a "whole-part" relationship. The combined pattern is consistent with the use of a single object (that is, the leaf object) and the combined object (that is, the container object), which can also be called the "whole-part" (part-whole) pattern, which is an object-structured pattern.

key: The key modules of combinatorial mode structure:

Abstract Artifacts (Component)

The object declaration interface in the combination implements the default behavior of all classes common interfaces, where appropriate. Declares an interface for accessing and managing component subassemblies.

Leaf component (Leaf)

In the composition, the leaf node of the tree is represented, and the leaf node has no sub-nodes.

Container Components (Composite)

Define parts with minor points, implement operations with subassemblies in the component interface, such as add and delete (remove).

Core: The key of the combinatorial mode is to define an abstract component class, which can represent both the leaf and the composite, while the client programs the abstract component class without knowing whether it represents a leaf or a container, and it can be processed uniformly. At the same time, the container object and the abstract component class also establish an aggregation association relationship, in the container object can contain both the leaf, can also contain the container, in order to realize the recursive combination, form a tree structure.

Usage Scenarios

In a hierarchical structure with a whole and a partial, you want to ignore the differences between the whole and the parts in one way, and clients can treat them consistently.

In a system developed using object-oriented language, a tree structure needs to be processed.

Leaf objects and container objects can be detached from one system, and their types are not fixed, and some new types need to be added.

Program Ape Instance

Hypothetical problem Environment:

Take the most common scenario of Android development to analyze it. One of our needs is to traverse all the files and folders in the entire cache folder and print them (the actual designation is not a print, but a logical operation, as demonstrated here). We do not use the combo mode as follows.

 PackageYanbober.github.io;ImportJava.util.ArrayList;ImportJava.util.list;class MediaFile {PrivateString Mname;PrivateString mdescription; Public MediaFile(String mname, String mdescription) { This. mname = Mname; This. mdescription = mdescription; }@Override     PublicStringtoString() {return "mediafile# name="+mname+", description="+mdescription; }}class Officefile {PrivateString Mname;PrivateString mdescription; Public Officefile(String mname, String mdescription) { This. mname = Mname; This. mdescription = mdescription; }@Override     PublicStringtoString() {return "officefile# name="+mname+", description="+mdescription; }}class PackageFile {PrivateString Mname;PrivateString mdescription; Public PackageFile(String mname, String mdescription) { This. mname = Mname; This. mdescription = mdescription; }@Override     PublicStringtoString() {return "packagefile# name="+mname+", description="+mdescription; }}class BaseFolder {PrivateString Mname;PrivateString mdescription;PrivateList<basefolder> mbasefolderlist =NewArraylist<> ();PrivateList<mediafile> mmediafilelist =NewArraylist<> ();PrivateList<officefile> mofficefilelist =NewArraylist<> ();PrivateList<packagefile> mpackagefilelist =NewArraylist<> (); Public BaseFolder(String mname, String mdescription) { This. mname = Mname; This. mdescription = mdescription; } Public void Addbasefolder(BaseFolder BaseFolder)    {Mbasefolderlist.add (BaseFolder); } Public void Addmediafile(MediaFile MediaFile)    {Mmediafilelist.add (MediaFile); } Public void Addofficefile(Officefile officefile)    {Mofficefilelist.add (officefile); } Public void Addpackagefile(PackageFile PackageFile)    {Mpackagefilelist.add (packagefile); }@Override     PublicStringtoString() {StringBuilder builder =NewStringBuilder ("*****basefolder# Enter folder is:"+mname+"\ n"); for(BaseFolder basefolder:mbasefolderlist) {Builder.append (basefolder.tostring () +"\ n"); } for(MediaFile mediafile:mmediafilelist) {Builder.append (mediafile.tostring () +"\ n"); } for(Officefile officefile:mofficefilelist) {Builder.append (officefile.tostring () +"\ n"); } for(PackageFile packagefile:mpackagefilelist) {Builder.append (packagefile.tostring () +"\ n"); }returnBuilder.tostring (); }} Public  class Main {     Public Static void Main(string[] args) {BaseFolder folder =NewBaseFolder ("Cache","App cache dir."); MediaFile MediaFile =NewMediaFile ("Test.png","test picture.");        Folder.addmediafile (MediaFile); MediaFile =NewMediaFile ("Haha.mp4","test video.");        Folder.addmediafile (MediaFile); PackageFile PackageFile =NewPackageFile ("yanbo.apk","an android application.");        Folder.addpackagefile (PackageFile); BaseFolder Childdir =NewBaseFolder ("word","Office dir."); Officefile Officefile =NewOfficefile ("Rrrr.doc","Office doc file.");        Childdir.addofficefile (Officefile);        Folder.addbasefolder (Childdir);    System.out.println (Folder.tostring ()); }}

With the implementation of the problem as above ...

As the above code, you will find that the client code relies too much on the complex internal implementation structure of the container object, the change of the internal implementation structure of the container object will cause the frequent change of the customer code, which brings the disadvantage of complicated code maintenance and expansibility. The introduction of combined mode will solve these problems to some extent.

What do you do? To raise a level Bai, use the combination mode.

L'm a class.

A refactoring of the code above? Then, according to the important core module of combinatorial mode structure, we will reconstruct the above code upgrade.

 PackageYanbober.github.io;ImportJava.util.ArrayList;ImportJava.util.List;AbstractClass Abstractcomponent { Public Abstract void Add(Abstractcomponent c); Public AbstractAbstractcomponentGet(intindex); Public AbstractStringgetString();} Class MediaFile extends Abstractcomponent {PrivateString Mname;PrivateString mdescription; Public MediaFile(String mname, String mdescription) { This. mname = Mname; This. mdescription = mdescription; }@Override     Public void Add(Abstractcomponent c) {//unused}@Override     PublicAbstractcomponentGet(intIndex) {return NULL; }@Override     PublicStringgetString() {return "mediafile# name="+mname+", description="+mdescription; }}class Officefile extends Abstractcomponent {PrivateString Mname;PrivateString mdescription; Public Officefile(String mname, String mdescription) { This. mname = Mname; This. mdescription = mdescription; }@Override     Public void Add(Abstractcomponent c) {//unused}@Override     PublicAbstractcomponentGet(intIndex) {return NULL; }@Override     PublicStringgetString() {return "officefile# name="+mname+", description="+mdescription; }}class PackageFile extends Abstractcomponent {PrivateString Mname;PrivateString mdescription; Public PackageFile(String mname, String mdescription) { This. mname = Mname; This. mdescription = mdescription; }@Override     Public void Add(Abstractcomponent c) {//unused}@Override     PublicAbstractcomponentGet(intIndex) {return NULL; }@Override     PublicStringgetString() {return "packagefile# name="+mname+", description="+mdescription; }}class BaseFolder extends Abstractcomponent {PrivateString Mname;PrivateString mdescription;PrivateList<abstractcomponent> abstractcomponents =NewArraylist<> (); Public BaseFolder(String mname, String mdescription) { This. mname = Mname; This. mdescription = mdescription; }@Override     Public void Add(Abstractcomponent c)    {Abstractcomponents.add (c); }@Override     PublicAbstractcomponentGet(intIndex) {returnAbstractcomponents.get (index); }@Override     PublicStringgetString() {StringBuilder builder =NewStringBuilder ("*****basefolder# Enter folder is:"+mname+"\ n"); for(Abstractcomponent basefolder:abstractcomponents) {Builder.append (basefolder.getstring () +"\ n"); }returnBuilder.tostring (); }} Public  class Main {     Public Static void Main(string[] args) {Abstractcomponent folder =NewBaseFolder ("Cache","App cache dir."); Abstractcomponent MediaFile =NewMediaFile ("Test.png","test picture.");        Folder.add (MediaFile); MediaFile =NewMediaFile ("Haha.mp4","test video.");        Folder.add (MediaFile); Abstractcomponent PackageFile =NewPackageFile ("yanbo.apk","an android application.");        Folder.add (PackageFile); BaseFolder Childdir =NewBaseFolder ("word","Office dir."); Abstractcomponent Officefile =NewOfficefile ("Rrrr.doc","Office doc file.");        Childdir.add (Officefile);        Folder.add (Childdir);    System.out.println (Folder.getstring ()); }}

The above example through the combination of pattern code has a good extensibility, when adding a new file type, without modifying the existing class library code, just add a new file class as a subclass of the Abstractfile class (do not have to modify the Basefolder in the Add), However, since a large number of methods for managing and accessing member artifacts are declared in Abstractfile, such as add (), we need to implement these methods in the new file class, providing corresponding error hints and exception handling. You will understand that, in fact, as the code can continue to optimize the implementation of each subclass of error hints and exception handling to the abstract base class as the default processing, which can also reduce code duplication. Ha ha.

sum up a

When you discover that a requirement is a partial and holistic hierarchy, and that you want users to be able to ignore the difference between a combined object and a single object, you should consider combining patterns when you use all the objects in a composite structure uniformly.

The advantages of the combined mode are as follows:

    • The combination mode can clearly define hierarchical complex objects, representing all or part of the object's hierarchy, which allows the client to ignore the hierarchical differences and facilitate control over the entire hierarchy.
    • Clients can consistently use a composite structure or a single object, without having to worry about whether they are dealing with a single object or the entire composition structure, simplifying client-side code.
    • It is convenient to add new container components and leaf components in the combined mode, and it is not necessary to make any modifications to the existing class library, which conforms to the "open and closed principle".
    • The combination mode provides a flexible solution for the object-oriented implementation of tree structure, which can form complex tree structure through the recursive combination of leaf object and container object, but the control of tree structure is very simple.

The disadvantages of combining patterns are as follows:

    • It is difficult to limit the types of artifacts in a container when adding new artifacts. Sometimes we want a container to have only certain types of objects, such as only text files in a folder, and when using composite mode, you cannot rely on the type system to impose these constraints, because they all come from the same abstraction layer, in which case it must be done by typing at run time, This implementation process is more complex.

"Craftsman Joshui Http://blog.csdn.net/yanbober" Continue reading "to be continued ... 》

Design pattern (structured) combined mode (Composite pattern)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.