An attractor expresses the desire of things for each other. In the case of UHR if the attraction of two parts is strong enough, they will bond in a manner similar to a molecular bond. Fulfilling an attraction (bonding) is said to "satisfy" the attraction, and results in a "link".
An attraction between two parts occurs when one has a service tne other one needs. We take this abstraction and express it in the UHR core as the needs and services that ServiceClients and ServiceHosts publish. Here's what the low level mechanism looks like:

A part implementing ServiceClient has zero or more ServiceNeeds. A ServiceNeed has an attractor, shown on the diagram as the Need Attractor. A part implementing ServiceHost has zero or more ServiceItems. A ServiceItem has an attractoir, shown as the Service Attractor. Thus needs and services each have an attractor.
Suppose you have a Printer part that publishes the Service Attractor shown. The UF_void_String_int Uniface is used to request the service to print String text a certain number of int copies. This particular Printer part can't handle color printing, but it can handle other normal work.
Somewhere else in the system we have a part that needs to print Black and White on Legal Size paper. It publishes the Need Attractor as shown.
When the container with the need is started, the need will be automatically satisfied by bonding with an attractor that can handle the need. For example, using the default matching logic, if the Need Attractor is a subset of the Service Attractor, we have a "Subset" match and a bond occurs. It's that simple.
The core offers a default "First Subset Match" algorithm, as shown and described above, or the ability for a ServiceNeed to pick the best service attractor from those available. This matching mechanism is patterned after the "templates" Java's Jini., which is patterned after ??? :-)
This simple attractor mechanism allows the part designer to express very complex semantic dependencies between parts without that complexity spilling out into the rest of the system. Plus that complexity is encapsulated and published in a standard mechanism. This has the effect of nearly elimininating the original complexity.
For small systems a single simplistic attribute (such as ServiceID) is just fine. For large systems multiple attributes are used.
The above shows a single Type for simplicity. Actually the Attractor supports multiple types. The "Subset" match actually considers whether the types needed are a subset of the service types.
For code level futher information see Javadoc for: