1. 什么是设计模式
设计模式是为了解决软件工程中常见的问题而被提出的一种反复证明的最佳实践或解决方法。它可以更好的组织代码,提高代码复用性和可维护性,以及保证代码的健壮性。
设计模式是在实践中总结出来的,并被一些优秀的程序员、设计师、架构师等编纂成书,并广泛应用于软件系统开发中。而且,这些模式可以适用于各种OO (面向对象) 语言,包括Java、C++、Python等。
本文介绍的是一种常见的按照类别分类的设计模式,这些模式分为三类:创建型模式、结构型模式和行为型模式。
2. 创建型模式
2.1 工厂方法模式
工厂方法模式是一种面向对象编程中常使用的设计模式,在工厂方法模式中,创建对象的工作由工厂类来完成。
例如,我们在创建对象时往往需要根据不同的参数,来创建不同的对象,而这样的对象又有不同的实现方式。在这种情况下,我们可以使用工厂方法来实现不同的对象创建。
class VehicleFactory:
def __init__(self):
pass
def create_vehicle(self, type):
pass
class Car(VehicleFactory):
def __init__(self):
pass
def create_vehicle(self, type):
if type == "sport":
return SportCar()
elif type == "family":
return FamilyCar()
else:
return None
class Bike(VehicleFactory):
def __init__(self):
pass
def create_vehicle(self, type):
if type == "mountain":
return MountainBike()
elif type == "road":
return RoadBike()
else:
return None
car_factory = Car()
bike_factory = Bike()
sport_car = car_factory.create_vehicle("sport")
family_car = car_factory.create_vehicle("family")
mountain_bike = bike_factory.create_vehicle("mountain")
road_bike = bike_factory.create_vehicle("road")
在上面的代码中,我们实现了一个车辆工厂,根据不同的类型来创建不同的车辆。其中,车辆工厂有一个create_vehicle的方法,用于根据不同的类型来创建车辆,而每个车辆又有不同的实现类。
由此可以看出,工厂方法模式可以很容易地扩展它的实现方式,同时可以遵循单一职责原则,确保对象的创建只是一个职责。
2.2 抽象工厂模式
抽象工厂模式是一种为了创建对象系列而设计的一种模式。它提供了一个接口,用于创建相关或依赖对象的家族,而不需要明确指定每个类的具体类。
例如,我们可以创建一个披萨店,它有两个分店,分别生产不同的披萨。
class PizzaFactory:
def __init__(self):
pass
def create_pizza(self, type):
pass
class NewYorkPizzaFactory(PizzaFactory):
def __init__(self):
pass
def create_pizza(self, type):
if type == "cheese":
return NewYorkCheesePizza()
elif type == "clam":
return NewYorkClamPizza()
else:
return None
class ChicagoPizzaFactory(PizzaFactory):
def __init__(self):
pass
def create_pizza(self, type):
if type == "cheese":
return ChicagoCheesePizza()
elif type == "clam":
return ChicagoClamPizza()
else:
return None
new_york_pizza_factory = NewYorkPizzaFactory()
chicago_pizza_factory = ChicagoPizzaFactory()
cheese_pizza = new_york_pizza_factory.create_pizza("cheese")
clam_pizza = chicago_pizza_factory.create_pizza("clam")
在上面的代码中,我们实现了一个披萨工厂,它有两个分店。这两个分店分别生产不同的披萨,每个分店生产的披萨有不同的实现方式,但是我们并没有明确指定每个类的具体类,而是使用了抽象类PizzaFactory。这样,我们可以很容易地扩展它的实现方式。
3. 结构型模式
3.1 适配器模式
适配器模式是一种将一个类的接口转换成客户希望的另一个接口的模式。它常用于需要复用一些现有的类,但是这些类的接口与客户端要求的接口不一致的情况下。
例如,我们需要将一个代码库,它的接口与我们需要的接口不一致,而我们又不希望修改这个代码库,这时候,使用适配器模式就可以很好地解决这个问题。
class Adaptee:
def specific_request(self):
return "Adaptee response"
class Target:
def request(self):
pass
class Adapter(Target):
def __init__(self, adaptee):
self.adaptee = adaptee
def request(self):
return self.adaptee.specific_request()
adaptee = Adaptee()
adapter = Adapter(adaptee)
result = adapter.request()
在上面的代码中,我们使用了适配器模式,将Adaptee的接口转换成了我们需要的Target的接口。
适配器模式,以此来封装目标类和适配者类的实现细节,达到不修改原有代码,让两个不兼容的接口可以协同工作。
3.2 装饰器模式
装饰器模式是一种动态地给对象添加额外的功能的方式,而不需要修改对象的代码。装饰器模式通常用于需要修改一组对象的行为,但是又不希望使用子类继承的情况。
例如,我们现在需要给一组对象添加一些额外的操作。我们可以通过装饰器模式,来实现这个需求。
class Component:
def operation(self):
pass
class ConcreteComponent(Component):
def operation(self):
return "ConcreteComponent"
class Decorator(Component):
def __init__(self, component):
self._component = component
def operation(self):
return self._component.operation()
class ConcreteDecoratorA(Decorator):
def __init__(self, component):
super().__init__(component)
def operation(self):
return f"ConcreteDecoratorA({self._component.operation()})"
class ConcreteDecoratorB(Decorator):
def __init__(self, component):
super().__init__(component)
def operation(self):
return f"ConcreteDecoratorB({self._component.operation()})"
component = ConcreteComponent()
decorator_a = ConcreteDecoratorA(component)
decorator_b = ConcreteDecoratorB(decorator_a)
result = decorator_b.operation()
在上面的代码中,我们定义了一个component对象,然后对它进行了两次装饰操作,最后调用了最后一个装饰器的operation方法。
4. 行为型模式
4.1 观察者模式
观察者模式是一种非常常用的设计模式,它定义了对象之间的一种一对多的依赖关系,这样一来,当一个对象发生改变时,它的所有依赖着都会得到通知并自动更新。
例如,我们现在需要一个组件,当它们的状态改变时需要通知所有的观察者。我们可以使用观察者模式来实现这个功能。
class Subject:
def attach(self, observer):
pass
def detach(self, observer):
pass
def notify(self):
pass
class ConcreteSubject(Subject):
_state = 0
_observers = []
def attach(self, observer):
print("Attached an observer")
self._observers.append(observer)
def detach(self, observer):
self._observers.remove(observer)
def notify(self):
print("Subject notifiying all observers...")
for observer in self._observers:
observer.update(self._state)
def update_state(self, state):
print("Setting state...")
self._state = state
self.notify()
class Observer:
def update(self, state):
pass
class ConcreteObserverA(Observer):
def update(self, state):
print(f"ConcreteObserverA gets the update:{state}")
class ConcreteObserverB(Observer):
def update(self, state):
print(f"ConcreteObserverB gets the update:{state}")
subject = ConcreteSubject()
observer_a = ConcreteObserverA()
observer_b = ConcreteObserverB()
subject.attach(observer_a)
subject.attach(observer_b)
subject.update_state(1)
subject.update_state(2)
subject.detach(observer_b)
subject.update_state(3)
在上面的代码中,我们定义了一个主题对象和两个观察者对象。我们将这两个观察者对象注册到主题对象中,并对主题进行了一些更新。而观察者对象接收到主题对象的通知之后,就会自动处理更新。
观察者模式是一种典型的松耦合的设计模式,它可以让我们更加方便地扩展应用程序中的对象。
4.2 策略模式
策略模式是一种定义一系列算法的方法,从概念上来说,算法可以相互替换,而且算法的变化不会影响到使用算法的客户。这个模式需要定义一个策略接口,然后定义一系列具体的策略实现,每个策略是相互独立,可以替换的。
例如,我们现在需要根据不同的打折策略来计算价格。我们可以使用策略模式来实现这个功能。
class Context:
def __init__(self, strategy):
self._strategy = strategy
def context_interface(self):
self._strategy.do_something()
class Strategy:
def do_something(self):
pass
class ConcreteStrategyA(Strategy):
def do_something(self):
print("Executing Strategy A")
class ConcreteStrategyB(Strategy):
def do_something(self):
print("Executing Strategy B")
context1 = Context(ConcreteStrategyA())
context1.context_interface()
context2 = Context(ConcreteStrategyB())
context2.context_interface()
在上面的代码中,我们先定义了一个策略接口Strategy,然后定义了两个具体的策略,我们在运行时使用不同的策略来调用context_interface方法,以获得不同的行为。
策略模式可以简化代码,同时可以支持运行时动态替换算法实现,而不需要使用条件语句或符合语句。
总结
本文介绍了常见的24种设计模式,分别属于创建型模式、结构型模式和行为型模式。每种模式都可以提供一种适用于不同场景的解决方案,从而提升代码的可维护性和可扩展性。
软件开发中设计模式的使用,可以帮助架构师和开发人员更好地完成复杂的项目和产品,成为其编程技能和能力的体现。相信这些模式的学习与练习可以告诉我们什么是良好和高效的代码编写,这对于我们提高编程能力以及应对实际项目开发将有巨大的帮助。