Design Pattern (1) - UML Class Diagram

1 Introduction

Starting from this section, we will learn design patterns together. What are our learning goals?

  1. Understand common design patterns and their usage scenarios;
  2. Analyze the use of design patterns in actual projects, figure out the actual intentions, and understand the author's design ideas;
  3. Try to use design patterns to iterate and refactor your own code;
  4. Improve software architecture design ideas.

I've been reading the Android source code recently, and I often come across some clever ways of writing in the code. Simple ones are like IFactory in MediaPlayerService. I know it's factory mode, but I'm not sure why it's used in this way; more complicated ones are like DeferredActions in NuPlayer. Mechanism, I can only slowly figure out how it works, and finally I can figure out a big difference; some features are not very distinctive, such as the wrapper in NuPlayer Source, I don't quite understand why it is written like this.

When studying some excellent engineering source code implementations, I often feel that the author's writing is obscure because I do not understand the design ideas; sometimes I suddenly figure out the author's intention and feel suddenly enlightened. Many times, even if we know some design or writing methods, we may not be able to use them flexibly. In order to enable beginners to write better code, predecessors have sorted out the commonly used techniques and design patterns in the writing process. In-depth study and Thinking about design patterns is very helpful for both reading and writing code.

2. UML class diagram

Huge projects often have quite a lot of complex classes. When reading these classes, we often use UML class diagrams to show complex class relationships. The following is a simple UML class diagram example:
Please add image description

  • Car is an abstract class;
  • The car inherits from the car, and its relationship with the car is the implementation relationship, which is represented by a dotted line with a hollow arrow;
  • There is also an inheritance relationship between cars and cars, and the relationship between them is a generalization relationship, represented by a solid line with an open arrow;
  • The relationship between the engine and the car is a combination, represented by a solid line with a solid arrow;
  • There is an aggregation relationship between students and classes, represented by a solid line with a hollow arrow;
  • The relationship between students and campus cards is represented by a solid line with an arrow;
  • Students need to use bicycles to go to school, and there is a dependency relationship with bicycles, which is represented by a dotted line with an arrow;

3. Relationship between classes

3.1. Realize relationships

To realize a relationship means to 抽象概念become 现实实现. Taking the above example, we only know that the car can move, but we don’t know what the car looks like or how to move, so it is just a concept. A car contains components such as an engine and a gearbox, and can be moved by pressing the accelerator; a bicycle has two tires and a handle, and can be moved by pressing the foot. Cars and bicycles turn nihilistic (abstract) concepts into reality, so dashed arrows are used to represent the realization relationship.

In the code, the implementation relationship is expressed as inheriting abstract classes.

3.2. Generalization relationship

The generalization relationship refers to 具体事物的不同形态. Taking the same example of a car, we already know that a car is composed of a gearbox, an engine, etc., but they can still be formed into different forms, such as cars and SUVs. They are both cars, but they have their own characteristics.

In the code, the generalization relationship is expressed as inheriting non-abstract classes;

Taking MediaPlayerInterface.h as an example, MediaPlayerInterface inherits from MediaPlayerBase and implements hardwareOutput. Is this relationship an implementation or a generalization relationship?

Personally, I think it is a generalization relationship, and MediaPlayerBase is generalized to use two players, software mixer and hardware output. Generalization relationships often modify base class methods or add external interfaces, which may affect the use of polymorphism (force conversion is required to call the new interface of the generalization class).

For example, MediaPlayerBase needs to be forced to be converted in actual use to realize the call of setAudioSink.

	sp<MediaPlayerBase> p = createPlayer(playerType);
    if (!p->hardwareOutput()) {
    
    
        mAudioOutput = new AudioOutput(mAudioSessionId, mAttributionSource,
                mAudioAttributes, mAudioDeviceUpdatedListener);
        static_cast<MediaPlayerInterface*>(p.get())->setAudioSink(mAudioOutput);
    }

Generalization relationships are rarely seen, so I will add them here next time I encounter them.

3.3. Aggregation relationship

The aggregation relationship means that 整体和个体the whole is composed of individuals, but the absence of the whole does not affect the individuals. For example, the relationship between buffer list and buffer, buffer can form a buffer list, and the absence of buffer list will not affect the buffer.

3.4. Combination relationship

The combination relationship represents 部分和整体a relationship, and it is quite different from the aggregation relationship. When the whole of the combination relationship does not exist, the parts will not exist, and vice versa.

Some people may not understand what "the whole does not exist, and the part does not exist; the part does not exist, the whole does not exist." Here is ACodec.h as an example. There is an mBufferChannel member in ACodec, and ACodec is destroyed , then mBufferChannel will be destroyed accordingly, and what is reflected here is the combination relationship; if mBufferChannel is destroyed, then ACodec will naturally not be able to work.

When looking at the examples of cars and engines before, there were some doubts. Obviously the engine can exist independently, but why is it still combined with the car? The current understanding is that if there were no cars, there would be no need for the engine to exist, so there would be no whole and no parts.

The combination relationship is stronger than the aggregation relationship, and the intensity is indicated by a black arrow.

In the code, aggregation relationships and combination relationships are usually reflected in member variables. You need to figure out which one they belong to.

3.5. Relationship

Personal understanding of the association relationship means that 拥有, for example, if a student owns a bicycle, then the student is associated with the bicycle.

In the code, the association relationship is also reflected in member variables, but it is an ownership relationship. Unlike the combination and aggregation above, they are not related at all, and they do not need a bicycle to form a person.

3.6. Dependencies

Dependency represents 调用a relationship, which is a temporary relationship and is reflected in the code as parameters passed in. For another example, a student rides a shared bicycle to school every day. The bicycle does not belong to the student, but the student needs to use the bicycle every day. This is a dependency relationship. If the student has a car, it may be classified as an associated relationship.

Okay, the above is my personal understanding of UML diagram drawing and the relationship between classes. If there is any mistake, please point it out~

Guess you like

Origin blog.csdn.net/qq_41828351/article/details/132702017