What 's a design pattern?
A pattern of appropriate solutions to problems that appear repeatedly in programming. Supports implementation of object-oriented program designed without waste. As being cataloged as a pattern Prevent reinforcement of wheels
Five ideas underlying the design-pattern
- Separate things that do not change from things that do not change
- Program is done for interface (not for implementation)
- Aggregate rather than inherit
- Delegation, delegation, delegation
- Do not make until you need it (YAGNI)
Program is done for interface (not for implementation)
Program as far as possible "general/abstract". (The interface here is not an interface as a built-in Java syntax, It means "one that raised the degree of abstraction" on a wider level. )
This reduces the degree of coupling of the whole code.
if ( is_car() ): my_car = Car() my_car.drive(200) else: my_plane = AirPlane() my_plane.fly(200)
Changes to the entire code are necessary (vulnerable to change) every time the vehicle increases.
High abstraction level, loosely coupled code
my_vehicle = get_vehicle() my_vehicle.travel(200)
Even if the number of vehicles increases, there is no need to change this code (strong against change).
Aggregate rather than inherit.
Inheritance creates undesirable connections.
- The behavior of subclass depends on the behavior of superclass.
- You can see the contents of the superclass from the subclass.
class Vehicle: def start_engine(self): # Process for moving the engine print("engine started") def stop_engine(self): # Process for stopping the engine print("engine stopped") class Car(Vehicle): def drive(self): self.start_engine() # driving.. self.stop_engine() car = Car() car.drive()
The implementation of the engine is visible from Car If you want to make a vehicle that does not use the engine, you need a large remodeling
→ You can not separate a variable part (Engine) from a part that is difficult to change (Vehicle).
Use aggregation. In other words,
Make objects have "references to other objects".
Avoid relationships where objects are something of something (is-a-kind-of) Make a relationship that has something (has-a).
Example of Car has a Engine
class Car: def __init__(self): self.engine = Engine() def drive(self): self.engine.start() # driving.. self.engine.stop() class Engine: def start(self): print ("engine started") def stop(self): print ("engine stopped") car = Car() car.drive()
The Engine is now separated from Vehicle and encapsulated.
This makes it possible for Engine to switch easily.
class Car: def __init__(self): self.engine = GasolineEngine() def drive(self): self.engine.start() # Drive with gasoline engine self.switch_to_diesel() # Drive with diesel engine self.engine.stop() def switch_to_diesel(self): self.engine = DieselEngine()
Delegation, delegation, delegation
Delegation (Like inheritance patterns) start_engine and stop_engine There are things I want to release outside the class.
Even in such a case, we leave the actual state of processing to the Engine class.
class Car: def __init__(self): self.engine = GasolineEngine() def drive(self): self.engine.start() # driving.. self.engine.stop() def switch_to_diesel(self): self.engine = DieselEngine() def start_engine(self): self.engine.start() def stop_engine(self): self.eigine.stop()
With this, we can create a class with the same function as inherited while realizing "Aggregate rather than inherit.". In other words,
The combination of aggregation and delegation is an alternative to strong and flexible inheritance.
※ Although start_engine and stop_engine seem to be useless code to write for delegation, It can be solved by using method_missing etc. This is a proxy pattern and we will explain it separately.
Do not make until you need it (YAGNI / You aren't Gonna Need It.)
I do not use "most likely to use in the future". Over-engineering to make it unnecessarily flexible
The design pattern itself is not a purpose. It should be used as a means to solve the problem and achieve its objective, not more.
A commandment to think about design patterns.