Delegate is more flexible than inheritance, can be configured dynamically, does not cause the growth of subclass series, and can realize multiple functions through the synthesis of objects (decorator)
Inheritance is relatively inflexible, and once a subclass is selected, it cannot be dynamically configured
Delegates are black box reuse (see the parent class method), inheritance is white box reuse, should use more delegates less inheritance
inheritance to break the package . Because the implementation of subclasses is closely related to the implementation of the parent class, any changes that are implemented by the parent class will cause changes in subclasses.
let the reuse mechanism play a role
Most people can understand the concepts of objects, interfaces, classes, inheritance, and so on. The real challenge, however, is to apply these concepts to build flexible, reusable software. Design patterns tell you how to do this.
Inheritance vs Synthesis
In the process of functional reuse of object-oriented systems, the two most common technologies are class inheritance and object synthesis. As we explained before, class inheritance allows you to define an implementation of another class through the implementation of a class. Reuse through subclasses is often referred to as "white box reuse." The term "white box" refers to visibility: through inheritance, the inner structure of the parent class is visible to the subclass.
Object compositing is an alternative to class inheritance. New functionality can be obtained by assembling or synthesizing objects. Object synthesis requires a well-defined interface for the object to be synthesized. This type of reuse is called "black box Reuse" because the internal details of the object are not visible.
Both inheritance and synthesis have their own advantages and disadvantages. The inheritance of a class is statically defined at compile time and can be implemented directly because of the direct support of the language. Class inheritance also makes it easier to modify the implementation when reused, and it can also affect the operations that it inherits (in the case of overloading) when the subclass overloads the part rather than all the operations.
Class inheritance has some drawbacks. First, because inheritance completes at compile time, it is not possible to alter the implementation inherited from its parent class at run time, and, worse, the parent class typically defines a partial physical representation of its subclasses. Because inheritance exposes the implementation details of the parent class to subclasses, there is the argument that inheritance breaks the encapsulation . Because the implementation of subclasses is closely related to the implementation of the parent class, any changes that are implemented by the parent class will cause changes in subclasses.
This implementation dependency can be problematic when you try to reuse a subclass, because the resulting implementation cannot fit into the new problem domain in every respect, so the parent class may be changed or rewritten. This dependency limits flexibility and ultimately limits reusability. The solution is to inherit only through abstract classes, because abstract classes usually provide little or no implementation at all.
Object compositing is an object that is dynamically completed at run time by obtaining a reference to another object. Compositing requires objects to indicate their interfaces, which requires careful design of interfaces to facilitate the use of objects with other objects. Because objects are accessed through their interfaces, we do not have to break the encapsulation. As long as you have the same type, any object can be replaced with another object at run time. Also, because the object's implementation is written according to its interface, this reduces implementation dependencies.
The object synthesis has another effect in the system design. The appointment of object synthesis can help you keep your class encapsulated and concentrate on a task. Your class and class levels will remain small and rarely appear to become unmanageable levels of monsters. On the other hand, object-based design will have more objects (in the case of fewer classes), and the behavior of the system depends on how they relate to each other rather than in a class.
Here we have the second object-oriented design principle:
take precedence over object synthesis instead of class inheritance
Ideally, you should achieve reuse without having to write new components, and you should be able to assemble the existing components and get the functionality you need through object compositing. This is rare, however, because the set of components that are available in practice is not very rich.
According to our experience, the design of the use of inheritance as a reuse technology is a bit excessive, in fact, more in the design of the appointment of object synthesis technology will lead to better reusability. In design mode, you will see the object synthesis application again and again.
Delegate
A delegate is a way to make a synthetic technology complete and inherit the same functionality in reuse. In a delegate, when processing a request, there are two objects involved: the recipient object delegates its actions to the client object (Representative). An analogy is that subclasses process requests that are sent to the parent class. However, in inheritance, an inherited operation can always point to the recipient object through the This member variable, whereas in the delegate, in order to achieve the same effect, the receiver passes itself to the client to let the delegate's action point to the recipient.
For example, instead of using a window class as a subclass of a rectangular class, a window class can reuse the behavior of a rectangular class by keeping a rectangular instance variable and delegating the detail behavior of the rectangle to it. In other words, the "window is rectangular" alternative is that the window can be a rectangle. By applying a delegate, a Window object can explicitly send a request to its rectangular object instance, and it may have to inherit these operations if the delegate is not adopted.
The main advantage of a delegate is that it is easy to synthesize (compose) behavior at runtime and to change the way it is synthesized. Assuming that the rectangle class and the Circle class have the same type, our windows can become rounded at run time by replacing the rectangular instance with a circle instance.
Delegates, along with other technologies that enhance software flexibility through object synthesis, have a common disadvantage: dynamic, highly parameterized software is more difficult to understand than relatively static software. In addition, there are run-time efficiency issues with delegates. Only when the simplification of the delegate exceeds its complexity, the delegate is a good design choice. It is difficult to say when to use a delegate because its efficiency depends on its application environment, and the judgment of efficiency depends on the experience of the designer in applying it. The best way to apply a delegate is when it is applied to a highly stylized environment----that is, in standard mode.
Several design patterns apply delegates, such as state mode, policy mode, and visitor mode. In state mode, an object delegates its request to the State object, and the state object represents its current state; In a policy pattern, an object delegates a detailed request to another object that represents the policy that carries the request; one object has only one state, but can have multiple policies for different requests. The purpose of both patterns is to change the behavior of the object by changing the object that the delegate requests. In visitor mode, the execution of each element of an object structure is always delegated to the visitor object.
Applications that are commissioned in other modes are not as important as the above patterns. Demodulator mode uses an object to coordinate the communication of other objects, demodulator objects are sometimes simple to perform operations directly with other objects, sometimes it submits a reference to itself, at this time the real use of the delegate; The responsibility chain object processes the request by passing the request along the object chain from one object to another. Sometimes, a request carries a reference to the original object that receives the request, at which point the pattern uses a delegate; the bridging pattern separates the implementation from its abstraction, and when the abstraction and the specific implementation match, the abstract can simply delegate the operation to the concrete implementation.
a delegate is a special case of object synthesis . This shows that, for code reuse, inheritance can always be replaced with an object-synthesis mechanism.