设计模式学习(四)——《大话设计模式》
1.泛型
允许在编码时使用类型参数,从而使得代码更加灵活、可重用。泛型可以应用于类、接口、方法中,通过这种方式,可以编写出适用于多种数据类型的通用代码,而不是针对每种数据类型编写重复的代码。
泛型的优势
- 类型安全:泛型提供编译时类型检查,这意味着你可以在编译阶段就捕获到类型错误,而不是在运行时。
- 代码重用:通过使用泛型,可以写出更加通用的代码,避免了为每种数据类型编写特定代码的需要。
- 性能提升:使用泛型可以避免在运行时进行类型转换,因为类型检查是在编译时完成的。这可以提升程序的性能。
泛型在设计模式中的应用
泛型在许多设计模式中都有应用,使得这些设计模式更加灵活和可重用。以下是一些常见设计模式中泛型的应用示例:
工厂模式(Factory Pattern):通过使用泛型,可以创建一个通用的工厂类,它能够返回任何类型的对象。这样就不需要为每种产品创建一个特定的工厂类。
单例模式(Singleton Pattern):虽然单例模式通常不直接使用泛型,但是可以通过泛型来实现一个通用的单例生成器,这样就可以为任何类创建单例实例。
观察者模式(Observer Pattern):通过使用泛型,可以定义一个通用的观察者接口和被观察者对象,使得它们可以处理多种类型的数据。
策略模式(Strategy Pattern):泛型可以使策略模式更加灵活,因为你可以定义一个接受泛型参数的策略接口,从而使得不同的策略实现可以处理不同类型的数据。
代码示例
#Python 3.5 引入了 typing 模块,通过 Type Hints 增加了对泛型的支持。
from typing import TypeVar, GenericT = TypeVar('T')class GenericBox(Generic[T]):def __init__(self, content: T):self.content = contentdef get_content(self) -> T:return self.contentint_box = GenericBox[int](123)
str_box = GenericBox[str]("Hello World")print(f"Integer Value: {int_box.get_content()}")
print(f"String Value: {str_box.get_content()}")
// JDK 5 开始引入了泛型,可以在类、接口、方法中使用泛型。
public class GenericBox<T> {private T t;public void set(T t) {this.t = t;}public T get() {return t;}public static void main(String[] args) {GenericBox<Integer> integerBox = new GenericBox<>();GenericBox<String> stringBox = new GenericBox<>();integerBox.set(10);stringBox.set("Hello World");System.out.printf("Integer Value :%d\n\n", integerBox.get());System.out.printf("String Value :%s\n", stringBox.get());}
}
//通过使用 void* 指针和函数指针来间接实现类似泛型的效果
#include <stdio.h>// 泛型交换函数
void swap(void *a, void *b, size_t size) {char buffer[size];memcpy(buffer, a, size);memcpy(a, b, size);memcpy(b, buffer, size);
}int main() {int a = 5, b = 10;printf("Before swap: a = %d, b = %d\n", a, b);swap(&a, &b, sizeof(int));printf("After swap: a = %d, b = %d\n", a, b);return 0;
}
2.委托与事件
委托(Delegation)和事件(Events)是实现低耦合、高内聚的设计原则的重要手段。它们允许软件组件以松散耦合的方式相互通信,增强了代码的可维护性和可扩展性。
委托 (Delegation)
委托是一种对象设计模式,允许对象外部的某个方法代表另一个对象来执行任务。这种模式在避免继承带来的复杂性和限制时非常有用,提供了一种灵活的替代方案。
在编程实践中,委托通常意味着将一个方法作为参数传递给另一个方法。这样做的好处是可以在运行时动态地改变方法的行为。
事件 (Events)
事件是一种使对象能够通知其他对象发生了某些事情的机制。当定义的事件发生时,已注册监听该事件的对象会收到通知并执行相应操作。这是观察者模式(Observer Pattern)的一种特殊实现。
事件广泛应用于图形用户界面(GUI)编程和异步编程中,允许应用程序响应用户操作、系统消息或其他触发条件,而无需硬编码所有可能的响应逻辑。
委托与事件在不同语言中的实现
//C# 语言对委托和事件有原生支持。委托是持有一个或多个方法的类型,而事件是基于委托的一种特殊类型,用于实现事件驱动编程
public delegate void MyDelegate(string message); // 委托定义public class Publisher {public event MyDelegate MyEvent; // 事件定义public void RaiseEvent() {MyEvent?.Invoke("Hello World!");}
}public class Subscriber {public void OnMyEvent(string message) {Console.WriteLine(message);}
}// 使用
Publisher publisher = new Publisher();
Subscriber subscriber = new Subscriber();
publisher.MyEvent += subscriber.OnMyEvent; // 事件订阅
publisher.RaiseEvent(); // 触发事件
//Java 中没有原生的委托概念,但可以通过接口实现类似的功能。Java 的事件处理通常基于监听器模式,特别是在Swing等GUI框架中。
interface MyListener {void onEventOccurred(String message);
}class Publisher {private List<MyListener> listeners = new ArrayList<>();public void addListener(MyListener listener) {listeners.add(listener);}public void raiseEvent() {for (MyListener listener : listeners) {listener.onEventOccurred("Hello World!");}}
}class Subscriber implements MyListener {@Overridepublic void onEventOccurred(String message) {System.out.println(message);}
}// 使用
Publisher publisher = new Publisher();
Subscriber subscriber = new Subscriber();
publisher.addListener(subscriber); // 添加监听器
publisher.raiseEvent(); // 触发事件
#Python 中没有专门的委托和事件关键字,但可以通过函数作为一等公民(first-class citizens)的特性来实现类似的功能。
#事件驱动编程可以通过回调函数和发布/订阅模式来实现。
class Publisher:def __init__(self):self.events = []def subscribe(self, callback):self.events.append(callback)def raise_event(self):for event in self.events:event("Hello World!")def subscriber(event_data):print(event_data)# 使用
publisher = Publisher()
publisher.subscribe(subscriber) # 订阅事件
publisher.raise_event() # 触发事件
3.初学
对软件设计模式中的类与实例、构造方法、方法重载、属性和修饰符、封装、继承、多态、重构、抽象类、集合、接口、泛型、委托与事件等知识进行了初步的学习和了解,后面再继续学习不同的软件设计模式。