This is the fourth day of my participation in the November Gwen Challenge. Check out the details: The last Gwen Challenge 2021
This article is excerpted from This is How Design Patterns should Be Learned
Implement the curriculum directory structure with transparent combination mode
Taking an online course as an example, we design a relational structure of the course. For example, we have introductory Java courses, artificial intelligence courses, Java Design Patterns, source code analysis, soft Skills, etc. Java Design Patterns, source code analysis, soft Skills are part of the Java Architect package, and each course is priced differently. However, no matter how these courses are combined, there are some commonalities, and the relationship between the whole and the part can be designed with the combination mode. Start by creating a top-level abstract component, the CourseComponent class.
/** * Created by Tom. */
public abstract class CourseComponent {
public void addChild(CourseComponent catalogComponent){
throw new UnsupportedOperationException("Add operation not supported");
}
public void removeChild(CourseComponent catalogComponent){
throw new UnsupportedOperationException("Delete operation not supported");
}
public String getName(CourseComponent catalogComponent){
throw new UnsupportedOperationException("Get name operation not supported");
}
public double getPrice(CourseComponent catalogComponent){
throw new UnsupportedOperationException("Get price operation not supported");
}
public void print(a){
throw new UnsupportedOperationException("Print operation not supported"); }}Copy the code
All possible methods are defined in this top-level abstract component, but instead of writing any logical code, exceptions are thrown directly. Now, some of you might wonder, why don’t you use abstract methods? Because the abstract method is used, the subclasses must be implemented, so that there are no subtle differences between the subclasses. So when a subclass inherits the abstract class, all it needs to do is override the methods of the parent class. Then create the Course class and CoursePackage class respectively. The code to create the Course class is as follows.
/** * Created by Tom. */
public class Course extends CourseComponent {
private String name;
private double price;
public Course(String name, double price) {
this.name = name;
this.price = price;
}
@Override
public String getName(CourseComponent catalogComponent) {
return this.name;
}
@Override
public double getPrice(CourseComponent catalogComponent) {
return this.price;
}
@Override
public void print(a) {
System.out.println(name + " (¥" + price + "Yuan)"); }}Copy the code
The code to create the CoursePackage class is as follows.
/** * Created by Tom. */
public class CoursePackage extends CourseComponent {
private List<CourseComponent> items = new ArrayList<CourseComponent>();
private String name;
private Integer level;
public CoursePackage(String name, Integer level) {
this.name = name;
this.level = level;
}
@Override
public void addChild(CourseComponent catalogComponent) {
items.add(catalogComponent);
}
@Override
public String getName(CourseComponent catalogComponent) {
return this.name;
}
@Override
public void removeChild(CourseComponent catalogComponent) {
items.remove(catalogComponent);
}
@Override
public void print(a) {
System.out.println(this.name);
for(CourseComponent catalogComponent : items){
// Control the display format
if(this.level ! =null) {for(int i = 0; i < this.level; i ++){
// Prints the space control format
System.out.print("");
}
for(int i = 0; i < this.level; i ++){
// Print a + sign at the beginning of each line
if(i == 0){ System.out.print("+"); }
System.out.print("-"); }}// Print the titlecatalogComponent.print(); }}}Copy the code
Finally write the client test code.
public static void main(String[] args) {
System.out.println("============ Transparent combination mode ===========");
CourseComponent javaBase = new Course(Introduction to Java.8280);
CourseComponent ai = new Course("Artificial intelligence".5000);
CourseComponent packageCourse = new CoursePackage("Java Architect Course".2);
CourseComponent design = new Course("Java Design Patterns".1500);
CourseComponent source = new Course("Source code analysis".2000);
CourseComponent softSkill = new Course("Soft skills".3000);
packageCourse.addChild(design);
packageCourse.addChild(source);
packageCourse.addChild(softSkill);
CourseComponent catalog = new CoursePackage("Course Main Catalogue".1);
catalog.addChild(javaBase);
catalog.addChild(ai);
catalog.addChild(packageCourse);
catalog.print();
}
Copy the code
The running result is shown in the figure below.
The transparent composite pattern defines all public methods in Component so that clients do not need to distinguish between leaf and branch objects; However, a leaf node inherits methods that it does not need (methods to manage subclass operations), which is contrary to the interface isolation principle of design pattern.
Implement an infinite level file system using secure combination mode
Take another example that programmers are more familiar with. For programmers, computers are a daily necessity. Computer file system is a typical tree structure, directory contains folders and files, folders can contain folders and files. The following code to achieve a directory system. File systems have two large hierarchies: folders and files. Among them, folders can accommodate other levels, which are branch nodes; A file is the smallest unit and is a leaf node. Because the directory system has few levels, and the structure of branch nodes (folders) is relatively stable, and files can actually have many types, we choose to use the safe combination mode to implement the directory system, so as to avoid introducing redundant methods for leaf node types (files). Start by creating the top-level abstract component Directory class.
public abstract class Directory {
protected String name;
public Directory(String name) {
this.name = name;
}
public abstract void show(a);
}
Copy the code
Then create the File and Folder classes, respectively. The code to create the File class is as follows.
public class File extends Directory {
public File(String name) {
super(name);
}
@Override
public void show(a) {
System.out.println(this.name); }}Copy the code
The code to create the Folder class is as follows.
import java.util.ArrayList;
import java.util.List;
public class Folder extends Directory {
private List<Directory> dirs;
private Integer level;
public Folder(String name,Integer level) {
super(name);
this.level = level;
this.dirs = new ArrayList<Directory>();
}
@Override
public void show(a) {
System.out.println(this.name);
for (Directory dir : this.dirs) {
// Control the display format
if(this.level ! =null) {for(int i = 0; i < this.level; i ++){
// Prints the space control format
System.out.print("");
}
for(int i = 0; i < this.level; i ++){
// Print a + sign at the beginning of each line
if(i == 0){ System.out.print("+"); }
System.out.print("-"); }}// Print the namedir.show(); }}public boolean add(Directory dir) {
return this.dirs.add(dir);
}
public boolean remove(Directory dir) {
return this.dirs.remove(dir);
}
public Directory get(int index) {
return this.dirs.get(index);
}
public void list(a){
for (Directory dir : this.dirs) { System.out.println(dir.name); }}}Copy the code
Note that the Folder class not only overrides the top-level show() method, but also adds the list() method. Finally write the client test code.
public static void main(String[] args) {
System.out.println("============ Security combination mode ===========");
File qq = new File("QQ.exe");
File wx = new File("WeChat. Exe");
Folder office = new Folder("Office Software".2);
File word = new File("Word.exe");
File ppt = new File("PowerPoint.exe");
File excel = new File("Excel.exe");
office.add(word);
office.add(ppt);
office.add(excel);
Folder wps = new Folder(Kingsoft software.3);
wps.add(new File("WPS.exe"));
office.add(wps);
Folder root = new Folder("Root directory".1);
root.add(qq);
root.add(wx);
root.add(office);
System.out.println("----------show() method effect -----------");
root.show();
System.out.println("----------list() method effect -----------");
root.list();
}
Copy the code
The running result is shown in the figure below.
The advantage of the security combination mode is that the interface definition responsibility is clear, and it conforms to the single responsibility principle and interface isolation principle of the design mode. The disadvantage is that clients need to distinguish between branch nodes and leaf nodes in order to properly handle each level of operation, and clients cannot rely on abstract interfaces (Components), violating the dependency inversion principle of design patterns.
Pay attention to “Tom play architecture” reply to “design pattern” can obtain the complete source code.
Tom play architecture: 30 real cases of design patterns (attached source code), the challenge of annual salary 60W is not a dream
This article is “Tom play structure” original, reproduced please indicate the source. Technology is to share, I share my happiness! If this article is helpful to you, welcome to follow and like; If you have any suggestions can also leave a comment or private letter, your support is my motivation to adhere to the creation. Pay attention to “Tom bomb architecture” for more technical dry goods!