One or three major characteristics
encapsulation
Use abstract data types to encapsulate data and data-based operations to form an indivisible independent entity. The data is protected inside the abstract data type, hiding the internal details as much as possible, and only retaining some external interfaces to connect it with the outside. The user does not need to know the internal details of the object, but can access the object through the interface provided by the object.
advantage:
- Reduce coupling: can be developed, tested, optimized, used, understood and modified independently
- Reduce the burden of maintenance: It can be easier to understand by programmers, and it does not affect other modules during debugging.
- Effectively tune performance: Profiling can determine which modules are impacting system performance
- Improve software reusability
- Reduces the risk of building large systems: even if the entire system is unavailable, these independent modules may be available
The following Person class encapsulates attributes such as name, gender, and age. The outside world can only obtain the name attribute and gender attribute of a Person object through the get() method, but cannot obtain the age attribute. However, the age attribute can be used by the work() method.
Note that the gender attribute is stored using the int data type, and encapsulation makes this implementation detail invisible to users. And when you need to modify the data type used by the gender attribute, you can do it without affecting the client code.
public class Person {
private String name;
private int gender;
private int age;
public String getName() {
return name;
}
public String getGender() {
return gender == 0 ? "man" : "woman";
}
public void work() {
if (18 <= age && age <= 50) {
System.out.println(name + " is working very hard!");
} else {
System.out.println(name + " can't work any more!");
}
}
}
inherit
Inheritance implementsIS-A relationship. For example, Cat and Animal are an IS-A relationship, so Cat can inherit from Animal. Thereby obtaining Animal's non-private properties and methods.
Inheritance should follow the Liskov substitution principle, and subclass objects must be able to replace all parent class objects.
Cat can be used as Animal, which means you can use Animal to reference the Cat object. The parent class reference pointing to the subclass object is called upcasting .
Animal animal = new Cat();
Polymorphism
Polymorphism is divided into compile-time polymorphism and run-time polymorphism:
- Compile-time polymorphism mainly refers to method overloading
- Runtime polymorphism means that the specific type pointed to by the object reference defined in the program is determined during runtime.
There are three conditions for runtime polymorphism:
- inherit
- Overwrite (rewrite)
- Upward transformation
In the code below, the instrument class (Instrument) has two subclasses: Wind and Percussion. They both override the play() method of the parent class, and use the parent class Instrument to refer to the Wind and Percussion objects in the main() method. When the play() method is called on an Instrument reference, the play() method of the class where the actual reference object is located will be executed, not the method of the Instrument class.
public class Instrument {
public void play() {
System.out.println("Instrument is playing...");
}
}
public class Wind extends Instrument {
public void play() {
System.out.println("Wind is playing...");
}
}
public class Percussion extends Instrument {
public void play() {
System.out.println("Percussion is playing...");
}
}
public class Music {
public static void main(String[] args) {
List<Instrument> instruments = new ArrayList<>();
instruments.add(new Wind());
instruments.add(new Percussion());
for(Instrument instrument : instruments) {
instrument.play();
}
}
}
2. Multiple relationships
Generalization
Used to describe inheritance relationships, use the extends keyword in Java.
@startuml
title Generalization
class Vehical
class Car
class Truck
Vehical <|-- Car
Vehical <|-- Truck
@enduml
Realization
To implement an interface, use the implements keyword in Java.
@startuml
title Realization
interface MoveBehavior
class Fly
class Run
MoveBehavior <|.. Fly
MoveBehavior <|.. Run
@enduml
Aggregation
It means that the whole is composed of parts, but the whole and the parts are not strongly dependent. If the whole does not exist, the parts will still exist.
@startuml
title Aggregation
class Computer
class Keyboard
class Mouse
class Screen
Computer o-- Keyboard
Computer o-- Mouse
Computer o-- Screen
@enduml
Composition
Different from aggregation, the whole and the parts in the combination are strongly dependent. If the whole does not exist, the parts will not exist either. For example, companies and departments. A company would not exist without departments. But the company and its employees have an aggregation relationship, because the company is gone and the employees are still there.
@startuml
title Composition
class Company
class DepartmentA
class DepartmentB
Company *-- DepartmentA
Company *-- DepartmentB
@enduml
Association
Indicates that there is an association between objects of different types. This is a static relationship that has nothing to do with the status of the running process and can be determined at the beginning. Therefore, it can also be represented by 1-to-1, many-to-1, and many-to-many relationships. For example, students and schools are related. A school can have many students, but a student only belongs to one school. Therefore, this is a many-to-one relationship that can be determined before the operation starts.
@startuml
title Association
class School
class Student
School "1" - "n" Student
@enduml
Dependency
Unlike associations, dependencies work during operation. There are three main forms of dependency relationships between classes A and B:
- Class A is a local variable (of a certain method) in class B;
- Class A is a parameter in the method of class B;
- Class A sends a message to class B, thereby affecting changes in class B;
@startuml
title Dependency
class Vehicle {
move(MoveBehavior)
}
interface MoveBehavior {
move()
}
note "MoveBehavior.move()" as N
Vehicle ..> MoveBehavior
Vehicle .. N
@enduml