-
Notifications
You must be signed in to change notification settings - Fork 0
Bridge Abstract Factory
Folder: 09-bridge-abstract-factory
Intent. Split an abstraction from its implementation so the two can change on their own. Instead of one class hierarchy that multiplies every combination, you get two hierarchies joined by a pointer.
How this code does it. bridgeFigures.cpp draws filled and hollow shapes. The abstraction is Figure, with Square as a concrete shape. The implementation is Fill, with Hollow, Filled, FullyFilled, and RandomFilled as concrete fills. A Figure holds a Fill*, so a square asks its fill for a border character and an internal character while drawing. Because the two sides are separate, I can add a new shape without touching any fill, or a new fill without touching any shape. RandomFilled is one I added; it returns a random one of its two characters each time it is asked.
classDiagram
class Figure {
#int size_
#Fill* fill_
+draw()* void
}
class Square {
+draw() void
}
class Fill {
#char border_
#char internal_
+getBorder()* char
+getInternal()* char
}
class Hollow
class Filled
class FullyFilled
class RandomFilled
Figure <|-- Square
Fill <|-- Hollow
Fill <|-- Filled
Fill <|-- FullyFilled
Fill <|-- RandomFilled
Figure o-- Fill : bridges to
Intent. Provide an interface for creating families of related objects without naming their concrete classes in the client.
How this code does it. The CarFactory hierarchy makes cars. CarFactory is the abstract factory with a protected makeCar, and FordFactory and ToyotaFactory are concrete factories that build Ford and Toyota products. The products share the abstract Car base. The client in CarTest.cpp holds a vector of CarFactory*, picks the least busy factory with std::accumulate, and calls requestCar, never naming Ford or Toyota. The factory method requestCar bumps a production counter and delegates to makeCar. CarBuyer.cpp is a second client I wrote: a car lot stocked from the factories where buyers test-drive cars until one matches the make and model they want.
classDiagram
class Car {
#string make_
#string model_
+getMake() string
+getModel() string
}
class Ford
class Toyota
class CarFactory {
+requestCar() Car*
#makeCar()* Car*
}
class FordFactory {
#makeCar() Car*
}
class ToyotaFactory {
#makeCar() Car*
}
Car <|-- Ford
Car <|-- Toyota
CarFactory <|-- FordFactory
CarFactory <|-- ToyotaFactory
FordFactory ..> Ford : makes
ToyotaFactory ..> Toyota : makes
g++ -std=c++17 09-bridge-abstract-factory/bridgeFigures.cpp -o figures
./figures
# the factory client needs the factory implementation on the line
g++ -std=c++17 09-bridge-abstract-factory/CarTest.cpp \
09-bridge-abstract-factory/CarFactory.cpp -o cartest
./cartestThe CarFactory interface and CarTest.cpp came from the course. The RandomFilled fill in the bridge demo and the whole CarBuyer.cpp client are mine. CarTest.cpp and CarBuyer.cpp call time() but rely on a transitive <ctime> include, so the CI force-includes that header to build them on any compiler.
Data structures & STL
Design patterns