Design Pattern Principles for ActionScript 3.0: Loose Coupling
Probably the best place to start a discussion of loose coupling is with an analogy. Suppose you’re on a trip away from home and you want to buy a gift for your child. You don’t know the town you’re in that well, and so you ask the receptionist at your hotel where you can find a toy store. The receptionist suggests a nearby store, and you go there. It’s a big toy store, and so you locate a clerk to help you find the toy you want. After showing you several toys of the kind you’re looking for, you proceed to select one and purchase it. You ask the clerk if you can have the toy gift-wrapped, and she takes the toy to the back room and has it wrapped for you.
The process to locate, purchase and have a toy gift-wrapped involves interacting directly with two people—the hotel receptionist and toy store clerk. A third person may have gift-wrapped the toy, but you don’t know and don’t care. All you care about is getting the toy and having it gift-wrapped. The process is smooth because you are loosely coupled with the people with whom you interact.
You Can’t Handle the Truth
Let’s suppose that the receptionist at the hotel just found out that his girlfriend ran off with a traveling design pattern developer and is heart-broken. You don’t need or want to know that. All you want from the interaction with the receptionist is the location of the toy store. You want loose coupling with the receptionist. Knowing about the receptionist’s internal turmoil won’t get you what you need and may needlessly complicate things because you too are a traveling design pattern developer. Interaction between hotel receptionists and hotel guests is well defined and restricted.
Further suppose that the clerk at the toy store has problems of her own. She’s just learned that her boyfriend is a sequential programmer. In the worst way she wants to talk with an OOP programmer, but she’s too embarrassed to talk with anyone she knows. Had she known you (a stranger) were an OOP programmer, you would have had to spend an extra hour listening to her pour her heart out and then lead an intervention to exorcize the sequential demon from her true love. However, like the receptionist, the relationship between toy store clerks and customers is well defined and restricted.
For a second, imagine that every interaction you have in daily life requires you to know the entire inner thoughts and experiences of the people with whom you interact, and they must have the same information about you. Your life and everyone else’s would be a rat’s nest of awkward coupling and you’d not be able to accomplish very much. However, because life is loosely coupled, most interactions are pretty smooth and you can get a lot done without having to take time that does not directly concern a request. (It’s also the reason that family reunions can be so stressful.)
Minimizing the Effects of Change: Just the Request
In your program, you want your class relationships to be well defined and restricted. Interfaces help keep relations both well defined and restricted. Because interfaces (abstract classes and interfaces) restrict the information details, you must focus on the request elements in the class. The request might be handled by instantiating a class instance that takes care of everything implied in the request. The request may need to have the right parameters or concrete class, but that should be through an interface. Then, if one of the implementations of the interface changes, everything still works because the request went through the interface, which should not change.
With loosely coupled classes you should be able to remove one and replace it with another implementation.
Just think of the clerk in the toy store. If she quit and a different clerk replaced her, the request for the toy and gift-wrapping would not change and the results would be equivalent. As for the wrapper in the back room, it could be the clerk or Snoop Dog; you don’t know or care. You just want the request met—a wrapped gift.
What about Delegation and Aggregation?
Using delegation, a request is sent to a class that handles the requirements of the request. We usually think of favoring composition over inheritance when using delegation. However, that does not mean that we do not employ loose coupling. On pages 56-57 of our book, you can see that using delegation also can go through an interface to choose the precise concrete class required for a request. So there’s no contradiction between using composition (via delegation) and loose coupling. In fact, delegation helps keep relations loose in that requests are sent to specialists through an interface that handle a request.
On the other hand, aggregation relations between classes seem to imply that you’ve got anything but loose coupling. After all, GoF differentiate between acquaintance and aggregation relations on the basis of a mutual lifetime of aggregation relationships. Think of two tennis players—when one stops playing; so does the other. So it is with aggregate relations.
Further, GoF note that acquaintance relations are weaker and suggest looser coupling between objects than aggregate relations. (GoF, p 23.) Here things get crumbly as far as I can see. (See No New is Good New for a detailed discussion of these two types of class relationships.) Apparently, language differences make a big difference in the nature of relationships characterized as acquaintance or aggregate. However, within a language, it can be tricky to differentiate an acquaintance from an aggregate. Like a lot of other caveats, GoF suggest that it depends on the intent.
In a recent post, we used a Strategy pattern that employs an aggregate relation between the Context class and Strategy interface. To make a request, the client both instantiates a Context instance and a concrete strategy using the following line:
private var context:Context=new Context(new PixLoader())
At first glance it may appear as though the request is through the concrete class PixLoader() directly. However, if you look at the Context class, you will see that the aggregate relationship between the Context and Strategy is through the abstract interface.
public function Context(lm:ILoadMaster):void
{
this.lm = lm;
}
So even with an aggregate relationship, the coupling is still loose. The concrete Strategy classes can be changed without the Client ever knowing and even getting near the details of the concrete Strategy classes. Likewise, the Context class makes all reference through the Strategy (ILoadMaster) interface, and so it too is loosely coupled to the concrete classes.
Into the Lunch Bucket
First of all, when you use a design pattern, all of the classes are set up in such as way that the relationships between classes are loosely coupled. Second, if you’re not sure about a relationship between classes, examine what each requires of the other. The extent to which the details of each class is behind an interface, you’re in pretty good shape. Some concrete classes, such as the Context class in the Strategy pattern, are not behind an interface; however, all of the operations in the Context class are abstract and reference in the interface with which it has an aggregate relationship.
For your lunch bucket principle, just keep this in mind,
Your classes can’t handle the truth.
and so remember, like the customer in the toy store,
All relations must be kept well defined and restricted.
Nobody needs to carry more baggage than they can handle. Don’t burden your classes with information from other classes they don’t need.
Related posts:

Bill Sanders
Nice. This is good information. Thank you for sharing.
I really like your use of analogies. It makes loose coupling so much easier to understand.
Thanks FlashDev2007,
Sometimes analogies link the known to the unknown; so I’m glad they made the connection for you.
Take care,
Bill
Yes, as FlashDev2007 already said above, great examples. Certainly a nice read.
Hi Ain,
Thanks. We’re starting a saturation plan to focus on just a few patterns and keep at them until everyone understands each one. That’s a change in tactics, and I hope it works.
Cheers,
Bill