The distinction between association, aggregation and composition as you describe it is a legacy going back to the old times of manual memory management. For example in C++ the memory used by objects has to be manually released and it is thus paramount to carefully design the lifecycle of composed objects. While the distinction between aggregation and composition is still being taught by many text books, it is essentially irrelevant when programming in environments with automatic memory management. If you have garbage collection all of them are just composition, period.
Encapsulation on the other hand is a much more general principle than what you describe. It is foremost the idea of bundling data and the functions that operate on this data in one module. One way to implement this is by keeping the state of the module private and expose changes to that state through public services. So client cannot access the state on their own but have to tell the module their intend by sending messages. So encapsulation is not limited to objects but applies to services as well. Actually, one way of looking at objects is to look at them as services.
Here's an example of encapsulation
public class Counter {
private int n = 0;
public int inc() { return n++; }
}
or the same using lambda functions
var counter = (function() {
var n = 0;
var inc = function() { return n++; }
return inc;
})();
In both cases the data, that is the variable n
, is bundled together with the function inc
that operates on it. And there is no way any other function could ever access n
, thus we have an encapsulated module that provides counting as a service.
NB: exposing all of an object's inner state through accessors is actually a violation of encapsulation. Alas, it is such a common violation that many will confuse it with good object-oriented design.
Although I generally agree with Bart van Ingen Schenau's answer, I think a few points need additional elaboration.
Th advantage of the 4+1 View Model is that it maps stakeholders to the type of information that they need, without requiring specific modeling notations to be used. The emphasis is on ensuring that all groups have the information to understand the system and continue to do their job.
The 4+1 View Model of Software Architecture was described in Philippe Kruchten's paper Architectural Blueprints - The "4+1" View Model of Software Architeture that was originally published in IEEE Software (November 1995). This publication doesn't make specific references to UML. In fact, the paper uses the Booch notation for the logical view, extensions to the Booch notation for process view and development view, calls out the use of "several forms" of developing a physical view, and a new notation for scenarios.
Instead of trying to map each of the views to particular types of diagrams, consider who the target audience of each view is and what information they need. Knowing that, look at various types of models and which one(s) provide the required information.
The logical view is designed to address the end user's concerns about ensuring that all of their desired functionality is captured by the system. In an object-oriented system, this is often at the class level. In complex systems, you may need a package view and decompose the packages into multiple class diagrams. In other paradigms, you may be interested in representing modules and the functions they provide. The end result should be a mapping of the required functionality to components that provide that functionality.
The process view is designed for people designing the whole system and then integrating the subsystems or the system into a system of systems. This view shows tasks and processes that the system has, interfaces to the outside world and/or between components within the system, the messages sent and received, and how performance, availability, fault-tolerance, and integrity are being addressed.
The development view is primarily for developers who will be building the modules and the subsystems. It should show dependencies and relationships between modules, how modules are organized, reuse, and portability.
The physical view is primarily for system designers and administrators who need to understand the physical locations of the software, physical connections between nodes, deployment and installation, and scalability.
Finally, the scenarios help to capture the requirements so that all the stakeholders understand how the system is intended to be used.
Once you understand what each view is supposed to provide, you can choose what modeling notations to use and at what level of detail is required. Bart's last paragraph is especially true - you can show various levels of details in your UML models by focusing on particular design elements or combining various types of diagrams into a set. In addition, you may want to consider going beyond UML to other modeling notations to better describe your system architecture - SysML, Entity-Relation modeling, or IDEF.
Best Answer
The question whether the relation between
ClassA
andClassB
is composite does not depend on whether there also instances ofClassB
that are not part of anyClassA
. In your example, as long as no reference to the innerClassB
-instance (the one held in your instance variablebInstance
) can ever escape the containing instance ofClassA
(which could happen if you have a public getter forbInstance
, for instance), you are perfectly fine modelling this as a composite relationship.In your UML model, it is the multiplicity of the container end that determines whether or not all
ClassB
-instances are expected to be part of someClassA
. The multiplicity of the container end can never be other than[0..1]
or[1..1]
in the first place, of course (otherwise this would violate the principle that an object can at most be part of a single composition); if it is[0..1]
you are saying that there can also beClassB
-instances not part of aClassA
; if it is[1..1]
then this is not the case.See also https://bellekens.com/2010/12/20/uml-composition-vs-aggregation-vs-association/ for an illuminating discussion.