设计模式按照其功能和用途大致可以分为创建型、结构型和行为型三大类。下面是这些类型的设计模式分类和示例的整理表格:
| 设计模式类型 | 模式名称 | 简要描述 |
|---|---|---|
| 创建型 | 单例模式(Singleton) | 确保类只有一个实例,并提供全局访问点。 |
| 工厂方法模式(Factory Method) | 定义一个创建对象的接口,但由子类决定实例化哪个类。 | |
| 抽象工厂模式(Abstract Factory) | 提供一个接口,用于创建相关对象的家族,而不指定具体类。 | |
| 建造者模式(Builder) | 使用多个简单对象一步步构建一个复杂对象。 | |
| 原型模式(Prototype) | 通过复制现有的对象来创建新对象,而不是通过构造函数。 | |
| 结构型 | 适配器模式(Adapter) | 将一个类的接口转换为客户端所期望的另一个接口。 |
| 装饰器模式(Decorator) | 动态地给对象添加新的职责,而不改变其结构。 | |
| 代理模式(Proxy) | 为其他对象提供一种代理或占位符,以便控制对该对象的访问。 | |
| 外观模式(Facade) | 为子系统中的一组接口提供统一的高层接口,使得子系统更易使用。 | |
| 桥接模式(Bridge) | 将抽象部分与实现部分分离,使得它们可以独立变化。 | |
| 组合模式(Composite) | 将对象组合成树形结构,以表示部分-整体的层次结构。 | |
| 享元模式(Flyweight) | 使用共享技术来有效地支持大量细粒度的对象。 | |
| 行为型 | 模板方法模式(Template Method) | 定义一个操作的算法骨架,将一些步骤的实现延迟到子类中。 |
| 策略模式(Strategy) | 定义一系列算法,将它们封装起来,使得它们可以互换使用。 | |
| 观察者模式(Observer) | 定义一种一对多的依赖关系,使得当一个对象的状态发生改变时,依赖它的对象会自动收到通知并更新。 | |
| 状态模式(State) | 允许对象在其内部状态改变时改变它的行为。 | |
| 迭代器模式(Iterator) | 提供一种方法顺序访问集合对象中的元素,而不暴露其内部结构。 | |
| 访问者模式(Visitor) | 将操作封装到访问者类中,使得可以对对象结构中的元素进行操作,而无需修改元素的类。 | |
| 命令模式(Command) | 将请求封装为对象,从而使用户能够参数化客户端请求、队列请求或记录请求。 | |
| 职责链模式(Chain of Responsibility) | 通过将请求沿着链传递,允许多个对象有机会处理该请求。 | |
| 中介者模式(Mediator) | 定义一个中介对象来封装一组对象之间的交互,以促进对象之间的松散耦合。 | |
| 备忘录模式(Memento) | 在不暴露对象实现细节的情况下,捕捉和恢复对象的内部状态。 | |
| 原型模式(Prototype) | 通过复制现有对象来创建新对象,而不是使用构造函数。 | |
| 解释器模式(Interpreter) | 为语言定义文法,并使用该文法解释语句。 | |
| 启动器模式(Mediator) | 在复杂对象之间协调交互。 |
总结
- 创建型模式:用于对象的创建和管理。
- 结构型模式:用于处理类或对象的组合结构。
- 行为型模式:用于定义类和对象之间的合作和职责分配。
1. 单例模式
- 饿汉模式
public class Hungry {
private Hungry() {
}
private static final Hungry HUNGRY = new Hungry();
public static Hungry getInstance() {
return HUNGRY;
}
}
- 懒汉模式
public class Lazy {
private volatile static Lazy LAZY = null;
private Lazy() {
}
public static Lazy getInstance() {
if (LAZY == null) {
synchronized (Lazy.class) {
if (LAZY == null) {
LAZY = new Lazy();
}
}
}
return LAZY;
}
}
- 枚举类
public enum Singleton {
INSTANCE;
// 可以添加单例类需要的方法
public void doSomething() {
System.out.println("Singleton instance is doing something.");
}
}
2. 工厂模式
- 简单工厂模式
简单工厂模式通过一个工厂类,根据传入的参数决定创建哪种具体产品。
结构:
- 工厂类:负责创建具体的产品对象。
- 产品类:被创建的对象。
- 客户端:通过调用工厂类的方法获取产品对象。
package factory;
// 产品接口
interface Product {
void use();
}
// 具体产品A
class ProductA implements Product {
public void use() {
System.out.println("使用产品A");
}
}
// 具体产品B
class ProductB implements Product {
public void use() {
System.out.println("使用产品B");
}
}
class SimpleFactory {
public static Product createProduct(String type) {
if ("A".equals(type)) {
return new ProductA();
} else if ("B".equals(type)) {
return new ProductB();
}
throw new RuntimeException("no such type");
}
}
// 客户端
public class Client {
public static void main(String[] args) {
Product product = SimpleFactory.createProduct("A");
product.use();
}
}
- 工厂方法模式
工厂方法模式将工厂类抽象化,使每个具体产品都有一个对应的工厂类来负责创建。
结构:
- 抽象工厂:定义工厂的接口。
- 具体工厂:实现工厂接口,负责创建具体产品。
- 产品接口:定义产品的公共行为。
- 具体产品:实现产品接口。
package factory;
// 产品接口
interface Product {
void use();
}
// 具体产品A
class ProductA implements Product {
public void use() {
System.out.println("使用产品A");
}
}
// 具体产品B
class ProductB implements Product {
public void use() {
System.out.println("使用产品B");
}
}
// 抽象工厂
interface Factory {
Product createProduct();
}
// A工厂
class FactoryA implements Factory{
@Override
public Product createProduct() {
return new ProductA();
}
}
// A工厂
class FactoryB implements Factory{
@Override
public Product createProduct() {
return new ProductB();
}
}
// 客户端
public class Client {
public static void main(String[] args) {
FactoryA factoryA = new FactoryA();
Product product = factoryA.createProduct();
product.use();
}
}
- 抽象工厂模式
抽象工厂模式用于创建一组相关或依赖的对象,而无需指定它们的具体类。
结构:
- 抽象工厂:定义创建一组产品的方法。
- 具体工厂:实现这些方法,生产具体的产品。
- 抽象产品:定义一类产品的接口。
- 具体产品:实现产品接口。
// 抽象产品A
public interface ProductA {
void use();
}
// 抽象产品B
public interface ProductB {
void play();
}
// 具体产品A1
public class ProductA1 implements ProductA {
public void use() {
System.out.println("使用产品A1");
}
}
// 具体产品A2
public class ProductA2 implements ProductA {
public void use() {
System.out.println("使用产品A2");
}
}
// 具体产品B1
public class ProductB1 implements ProductB {
public void play() {
System.out.println("播放产品B1");
}
}
// 具体产品B2
public class ProductB2 implements ProductB {
public void play() {
System.out.println("播放产品B2");
}
}
// 抽象工厂
public interface AbstractFactory {
ProductA createProductA();
ProductB createProductB();
}
// 具体工厂1
public class Factory1 implements AbstractFactory {
public ProductA createProductA() {
return new ProductA1();
}
public ProductB createProductB() {
return new ProductB1();
}
}
// 具体工厂2
public class Factory2 implements AbstractFactory {
public ProductA createProductA() {
return new ProductA2();
}
public ProductB createProductB() {
return new ProductB2();
}
}
// 客户端
public class Client {
public static void main(String[] args) {
AbstractFactory factory = new Factory1();
ProductA productA = factory.createProductA();
ProductB productB = factory.createProductB();
productA.use();
productB.play();
}
}
3. 策略模式
策略模式(Strategy Pattern)是一种行为型设计模式,旨在定义一系列算法或行为,将它们封装到独立的类中,并使它们可以互相替换,客户端代码可以动态地选择使用不同的算法或行为,而无需修改自身代码。
// 策略接口
public interface PaymentStrategy {
void pay(int amount);
}
// 具体策略:支付宝支付
public class AlipayStrategy implements PaymentStrategy {
public void pay(int amount) {
System.out.println("使用支付宝支付了:" + amount + "元");
}
}
// 具体策略:微信支付
public class WeChatPayStrategy implements PaymentStrategy {
public void pay(int amount) {
System.out.println("使用微信支付了:" + amount + "元");
}
}
// 具体策略:银行卡支付
public class BankCardStrategy implements PaymentStrategy {
public void pay(int amount) {
System.out.println("使用银行卡支付了:" + amount + "元");
}
}
// 上下文类:用于管理策略
public class PaymentContext {
private PaymentStrategy strategy;
// 设置策略
public void setStrategy(PaymentStrategy strategy) {
this.strategy = strategy;
}
// 执行支付操作
public void executePayment(int amount) {
if (strategy == null) {
throw new IllegalStateException("未设置支付策略");
}
strategy.pay(amount);
}
}
// 客户端
public class Client {
public static void main(String[] args) {
PaymentContext context = new PaymentContext();
// 使用支付宝支付
context.setStrategy(new AlipayStrategy());
context.executePayment(100);
// 切换为微信支付
context.setStrategy(new WeChatPayStrategy());
context.executePayment(200);
// 切换为银行卡支付
context.setStrategy(new BankCardStrategy());
context.executePayment(300);
}
}
4. 模板模式
模板模式(Template Method Pattern)是一种行为型设计模式,用于定义一个操作的算法骨架,而将一些步骤的实现延迟到子类中。模板模式使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。
结构:
- 抽象类(AbstractClass):定义了模板方法和一些步骤的抽象或默认实现。
- 具体子类(ConcreteClass):实现或重写抽象类中的步骤方法。
- 模板方法(TemplateMethod):在抽象类中定义的一个算法骨架,调用各个步骤的方法。
制作饮料的模板(如咖啡和茶)
// 抽象类:定义了模板方法和钩子方法
public abstract class Beverage {
// 模板方法
public final void prepareRecipe() {
boilWater();
brew();
pourInCup();
addCondiments();
if (isHook()) {
hook();
}
}
abstract void brew(); // 决定冲泡过程的具体实现
abstract void addCondiments(); // 添加配料的具体实现
void boilWater() {
System.out.println("烧开水");
}
void pourInCup() {
System.out.println("将饮料倒入杯子");
}
// 钩子方法
boolean isHook() {
return true;
}
// 可选的钩子方法
void hook() {
System.out.println("添加额外的步骤或行为");
}
}
// 具体子类:咖啡
public class Coffee extends Beverage {
@Override
void brew() {
System.out.println("用咖啡机冲泡咖啡");
}
@Override
void addCondiments() {
System.out.println("添加糖和牛奶");
}
}
// 具体子类:茶
public class Tea extends Beverage {
@Override
void brew() {
System.out.println("用茶叶冲泡茶");
}
@Override
void addCondiments() {
System.out.println("添加柠檬");
}
@Override
boolean isHook() {
return false; // 不使用钩子方法
}
}
// 客户端
public class Client {
public static void main(String[] args) {
Beverage coffee = new Coffee();
coffee.prepareRecipe();
System.out.println();
Beverage tea = new Tea();
tea.prepareRecipe();
}
}
5. 适配器模式
适配器模式(Adapter Pattern)是一种结构型设计模式,旨在将一个类的接口转换成客户端所期望的另一种接口。通过适配器模式,可以让原本接口不兼容的类一起工作。适配器模式通常用于旧代码与新系统之间的接口转换,或者将不同接口的类组合起来使用。
// 目标接口:客户端希望使用的接口
public interface Printer {
void print(String text);
}
// 被适配类:现有的类,其接口不符合目标接口
public class OldPrinter {
public void oldPrint(String text) {
System.out.println("旧打印机打印内容:" + text);
}
}
// 适配器类:将被适配类的接口转换为目标接口
public class PrinterAdapter implements Printer {
private OldPrinter oldPrinter;
public PrinterAdapter(OldPrinter oldPrinter) {
this.oldPrinter = oldPrinter;
}
@Override
public void print(String text) {
// 调用旧打印机的方法
oldPrinter.oldPrint(text);
}
}
// 客户端
public class Client {
public static void main(String[] args) {
OldPrinter oldPrinter = new OldPrinter();
Printer printer = new PrinterAdapter(oldPrinter);
// 客户端调用目标接口的方法
printer.print("Hello, world!");
}
}