Detailed explanation of composite mechanism in Java
This article mainly introduces relevant information about the detailed examples of composite mechanism in Java. I hope that through this article, everyone can understand the difference between inheritance and composite and apply the composite mechanism. Friends in need can refer to it
Detailed explanation of examples of composite mechanisms in java
The defects of inheritance
The defects of inheritance are caused by its overly powerful functions . Inheritance makes the subclass dependent on the implementation of the superclass. From this point of view, it does not comply with the principle of encapsulation.
Once the superclass changes with a version release, the subclass may be broken, even if its code has not changed at all.
In order to explain more specifically, assuming that we are using HashSet in our program now, we need to add a function to count how many elements have been added to this HashSet since it was created.
Without knowing the flaws of inheritance, we designed a class that inherited HashSet, added an attribute addCount for statistics, and overridden the add and addAll methods. In the method Modify the value of addCount,
The code is as follows:
public class InstrumentedHashSet<E> extends HashSet<E> { // The number of attempted element insertions private int addCount = 0; public InstrumentedHashSet() { } public InstrumentedHashSet(int initCap, float loadFactor) { super(initCap, loadFactor); } @Override public boolean add(E e) { addCount++; return super.add(e); } @Override public boolean addAll(Collection<? extends E> c) { addCount += c.size(); return super.addAll(c); } public int getAddCount() { return addCount; } }
This class looks reasonable, but it does not work properly. Execute this paragraph Code:
public static void main(String[] args) { InstrumentedHashSet<String> s = new InstrumentedHashSet<String>(); s.addAll(Arrays.asList("Snap", "Crackle", "Pop")); System.out.println(s.getAddCount()); // expect 3 but 6 }
Because only three elements were inserted, we expected the getAddCount method to return 3, but in fact it returned 6. What went wrong?
In fact, within HashSet, the addAll method is implemented based on the add method. Therefore, using addAll to add three elements will call addAll once and add three times.
Looking at our overridden method, we will understand why getAddCount returns 6.
Of course, you will say that since HashSet is implemented in this way, then we don’t need to override the addAll method. Yes, that's right.
But although this can work normally, its correctness depends on the fact that the addll method of HashSet is implemented on the add method.
Once the super class modifies the implementation details, our functions may be affected.
In general, inheritance has three natural flaws, which will make the software very fragile:
1) If the subclass calls the method of the parent class, then it will It forms a dependency on the parent class. Once the parent class is changed, the subclass may not work properly.
2) If the parent class adds a new method, and the subclass happens to already provide a method with the same signature but a different return value, then the subclass will not be able to compile.
3) Using inheritance when it should not be done will expose unnecessary APIs to subclasses. In this regard, the Java platform has made mistakes. A typical example is that Properties inherits HashTable, which is unreasonable. The property list is not a hash table, but the Properties in the Java code inherits HashTable. As a result, after the user creates a Properties instance, there is a put There are two methods, setProperties and getProperties. The put and get methods should not be exposed to users.
Because in Properties, both key and value should be String, and HashMap can be other types or even objects.
public class TestProperty { public static void main(String[] args) { Properties properties = new Properties(); properties.setProperty("aaa", "aaa"); properties.put("aaa", new TestPropertyObj()); System.out.println(properties.getProperty("aaa")); // null System.out.println(properties.get("aaa")); // com.hzy.effjava.chp3.item16.TestProperty$TestPropertyObj@5f4fcc96 } static class TestPropertyObj { } }
Composite alternatives to inheritance
The previous section talked about the shortcomings of inheritance, this one Let us take a look at the solution to this problem - compounding.
First we need a class that holds a Set object. This class implements the Set interface. The implementation method calls the corresponding method of the Set object held, so we also call it forwarding. Class:
public class ForwardingSet<E> implements Set<E> { private final Set<E> s; public ForwardingSet(Set<E> s) { this.s = s; } public void clear() { s.clear(); } public boolean contains(Object o) { return s.contains(o); } public boolean isEmpty() { return s.isEmpty(); } public int size() { return s.size(); } public Iterator<E> iterator() { return s.iterator(); } public boolean add(E e) { return s.add(e); } public boolean remove(Object o) { return s.remove(o); } public boolean containsAll(Collection<?> c) { return s.containsAll(c); } public boolean addAll(Collection<? extends E> c) { return s.addAll(c); } public boolean removeAll(Collection<?> c) { return s.removeAll(c); } public boolean retainAll(Collection<?> c) { return s.retainAll(c); } public Object[] toArray() { return s.toArray(); } public <T> T[] toArray(T[] a) { return s.toArray(a); } @Override public boolean equals(Object o) { return s.equals(o); } @Override public int hashCode() { return s.hashCode(); } @Override public String toString() { return s.toString(); } }
Then, we can design a class with statistical functions. We only need to inherit the forwarding class we just created, and then the statistical logic code Just write:
public class InstrumentedSet<E> extends ForwardingSet<E> { private int addCount = 0; public InstrumentedSet(Set<E> s) { super(s); } @Override public boolean add(E e) { addCount++; return super.add(e); } @Override public boolean addAll(Collection<? extends E> c) { addCount += c.size(); return super.addAll(c); } public int getAddCount() { return addCount; } public static void main(String[] args) { InstrumentedSet<String> s = new InstrumentedSet<String>(new HashSet<String>()); s.addAll(Arrays.asList("Snap", "Crackle", "Pop")); System.out.println(s.getAddCount()); } }
This implementation method avoids all the problems mentioned in the previous section. Since inheritance is not used, it does not depend on the super class. Implementation logic, there is no need to worry about the impact of new methods added to the super class on us.
And there is another advantage of writing this way. This class can add statistical functions to all classes that implement the Set interface, not just HashSet, but also other Sets such as TreeSet.
In fact, this is the decoration mode. InstrumentedSet modifies Set and adds a counting attribute to it.
Summary
Inheritance will destroy the encapsulation of the class, making the subclass very fragile and easily damaged.
Use the composite method to modify the super class to make the subclass more robust and more powerful.
The above is the detailed content of Detailed explanation of composite mechanism in Java. For more information, please follow other related articles on the PHP Chinese website!

The article discusses using Maven and Gradle for Java project management, build automation, and dependency resolution, comparing their approaches and optimization strategies.

The article discusses creating and using custom Java libraries (JAR files) with proper versioning and dependency management, using tools like Maven and Gradle.

The article discusses implementing multi-level caching in Java using Caffeine and Guava Cache to enhance application performance. It covers setup, integration, and performance benefits, along with configuration and eviction policy management best pra

The article discusses using JPA for object-relational mapping with advanced features like caching and lazy loading. It covers setup, entity mapping, and best practices for optimizing performance while highlighting potential pitfalls.[159 characters]

Java's classloading involves loading, linking, and initializing classes using a hierarchical system with Bootstrap, Extension, and Application classloaders. The parent delegation model ensures core classes are loaded first, affecting custom class loa


Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

AI Hentai Generator
Generate AI Hentai for free.

Hot Article

Hot Tools

SublimeText3 Chinese version
Chinese version, very easy to use

SublimeText3 Mac version
God-level code editing software (SublimeText3)

SecLists
SecLists is the ultimate security tester's companion. It is a collection of various types of lists that are frequently used during security assessments, all in one place. SecLists helps make security testing more efficient and productive by conveniently providing all the lists a security tester might need. List types include usernames, passwords, URLs, fuzzing payloads, sensitive data patterns, web shells, and more. The tester can simply pull this repository onto a new test machine and he will have access to every type of list he needs.

Dreamweaver Mac version
Visual web development tools

PhpStorm Mac version
The latest (2018.2.1) professional PHP integrated development tool