65: Design Patterns: Bridge.
Take Up Code - Un pódcast de Take Up Code: build your own computer games, apps, and robotics with podcasts and live classes
Categorías:
The bridge structural pattern allows you to separate an interface from its implementation. Maybe you want to start out doing something one way and then change later. Or maybe you want to share an implementation. Or, if you’re using C++, you can hide how you’re doing something. This is a subtle pattern with a lot of potential. Maybe you’re creating an application with vehicles in it. This could be a racing game or a driver certification application. You create a base class called Vehicle and derived classes Car, Truck, and Tractor which each inherit from the Vehicle class. Then you need different kinds of engines and since there’s a difference in behavior, you plan to create more classes to specialize. The problem is that not only does this lead to a lot of classes such as GasCar, DieselCar, GasTruck, DieselTruck, and DieselTractor, but you can’t change the type of engine in a car. Why would you need to do that? Cars always have the same engine, right? Even in real life, vehicles can sometimes change. And this is software. Everything changes in software. Instead of creating so many derived classes, a better solution will use the bridge pattern to form a link between the basic vehicle types and the engine types. This allows both vehicles and engines to be subclassed or derived from independently of each other. and because this pattern uses composition instead of inheritance, you can easily swap an engine type for another. Listen to the full episode for more about this pattern or read the full transcript below. Transcript The basic description says that this pattern lets abstractions decouple from implementations so they can both change independently. You learned about the adapter pattern yesterday which lets you use classes that weren’t designed to be used together. Well, this pattern, lets classes that are designed to be used separately be used together and mixed around if you want. This is a difficult pattern to understand without an example so let’s say you’re building a game with vehicles in it. You have cars, trucks, and tractors so you create an abstract class called Vehicle to represent all vehicles and you declare the classes Car, Truck, and Tractor to each derive from Vehicle. So far everything is going well. But then you realize that your vehicles can have either a gasoline engine or a diesel fuel engine with different behaviors each. Now what do you do? You could create some more subclasses. This would give you a GasCar, DieselCar, GasTruck, DieselTruck, and you go with just DieselTractor because you’ve never heard of a gasoline powered tractor. The number of classes is already increasing. Then you remember electric engines and create yet more classes. Hydrogen fuel cells? You got it. More classes. And just what are you going to do about a car that starts out with a gasoline engine until some engineer modifies it to use a futuristic capacitor instead? That won’t happen, right? This whole example is just made up. Yet this is exactly the sort of decisions you need to make as a software developer. Because you don’t want to be responsible for a design that works well for version one, then requires a complete re-write for version two. It’ll happen if you don’t plan for flexibility and fail to incorporate design patterns like this that have been proven over and over to represent some really good approaches. I’ll explain how you can improve the vehicle and engine dilemma by using the bridge pattern right after this message from our sponsor. ( Message from Sponsor ) The big problem with using inheritance, other than the huge number of classes you end up with, is that inheritance fixes or locks in place the implementation at design time. Sure, you get excellent types that are unique and specific but they become set in stone. You’ll need to come up with a whole new FirstGasThenFusionCar class when really all that’s happening is that