以下是关于 21 种设计模式的叙述和相应的 Java 代码示例:
**一、创建型模式**
1. **简单工厂模式**:
- 设计思想:通过单个方法或多个方法来创建产品对象,将产品的创建逻辑集中在一个工厂类中。
- 应用场景:当需要创建的产品种类相对较少,且创建逻辑相对简单时适用。
public class Singleton {
private static Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
public void showMessage() {
System.out.println("这是一个单例模式的示例");
}
}
2. **工厂方法模式**:
- 设计思想:定义一个用于创建对象的接口,让子类决定实例化哪一个类。它将产品的创建延迟到子类中进行。
- 应用场景:当一个类需要由其子类来决定创建何种具体对象时非常有用。例如,当需要增加新的产品类型时,只需添加相应的工厂子类,无需修改现有代码,具有较好的扩展性。
interface Product {
void doSomething();
}
class ConcreteProductA implements Product {
@Override
public void doSomething() {
System.out.println("ConcreteProductA 执行操作");
}
}
class ConcreteProductB implements Product {
@Override
public void doSomething() {
System.out.println("ConcreteProductB 执行操作");
}
}
abstract class Creator {
abstract Product createProduct();
}
class ConcreteCreatorA extends Creator {
@Override
Product createProduct() {
return new ConcreteProductA();
}
}
class ConcreteCreatorB extends Creator {
@Override
Product createProduct() {
return new ConcreteProductB();
}
}
3. **抽象工厂模式**:
- 设计思想:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。抽象工厂中有一个或多个抽象方法用于产生具体的产品组合;抽象产品是产品的纯虚基类;具体工厂继承抽象工厂,根据实际需要产生具体产品组合;具体产品继承抽象产品。
- uml 类图:[此处可插入抽象工厂模式的 UML 类图]
- 使用场景:当需要创建一系列相关的产品对象,且这些产品对象之间存在一定的约束关系时适用。
interface AbstractFactory {
ProductA createProductA();
ProductB createProductB();
}
interface ProductA {
void doA();
}
interface ProductB {
void doB();
}
class ConcreteFactory1 implements AbstractFactory {
@Override
public ProductA createProductA() {
return new ConcreteProductA1();
}
@Override
public ProductB createProductB() {
return new ConcreteProductB1();
}
}
class ConcreteFactory2 implements AbstractFactory {
@Override
public ProductA createProductA() {
return new ConcreteProductA2();
}
@Override
public ProductB createProductB() {
return new ConcreteProductB2();
}
}
class ConcreteProductA1 implements ProductA {
@Override
public void doA() {
System.out.println("ConcreteProductA1 操作");
}
}
class ConcreteProductA2 implements ProductA {
@Override
public void doA() {
System.out.println("ConcreteProductA2 操作");
}
}
class ConcreteProductB1 implements ProductB {
@Override
public void doB() {
System.out.println("ConcreteProductB1 操作");
}
}
class ConcreteProductB2 implements ProductB {
@Override
public void doB() {
System.out.println("ConcreteProductB2 操作");
}
}
4. **单例模式**:
- 设计思想:确保一个类只有一个实例存在,并提供一个全局访问点。在 Java 应用中,单例对象能保证在一个 JVM 中只有一个实例。
- 使用场景:当某些类在整个系统中只能存在一个实例时,如交易所的核心交易引擎、文件系统管理类或一个应用中的唯一实例(如 UIApplication)等。
public class Singleton {
private static Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
public void showMessage() {
System.out.println("这是一个单例模式的示例");
}
}
5. **建造者模式**:
- 设计思想:将复杂对象的构造与它的实现相分离,让相同的构建过程可以创建不同的对象。该模式包含创建者(builder)接口、具体创建者(concrete builder)、具体创建者管理对象(director)和复杂产品对象(product)等角色。
- 使用场景:复杂对象的算法应该独立于该对象的组成部分,或者当构造过程允许被构造出不同的对象时适用。
class Computer {
private String cpu;
private String ram;
private String hardDisk;
// 省略 getters 和 setters
@Override
public String toString() {
return "Computer{" +
"cpu='" + cpu + '\'' +
", ram='" + ram + '\'' +
", hardDisk='" + hardDisk + '\'' +
'}';
}
}
interface ComputerBuilder {
ComputerBuilder setCpu(String cpu);
ComputerBuilder setRam(String ram);
ComputerBuilder setHardDisk(String hardDisk);
Computer build();
}
class ConcreteComputerBuilder implements ComputerBuilder {
private Computer computer = new Computer();
@Override
public ComputerBuilder setCpu(String cpu) {
computer.setCpu(cpu);
return this;
}
@Override
public ComputerBuilder setRam(String ram) {
computer.setRam(ram);
return this;
}
@Override
public ComputerBuilder setHardDisk(String hardDisk) {
computer.setHardDisk(hardDisk);
return this;
}
@Override
public Computer build() {
return computer;
}
}
6. **原型模式**:
- 设计思想:将一个对象作为原型,通过复制、克隆的方式产生一个和原对象类似的新对象。
- 使用场景:适用于复制、克隆对象的场景,例如当创建一个实例的过程较为复杂,或者创建的对象子对象组合较多时。
class Prototype implements Cloneable {
private int id;
public Prototype(int id) {
this.id = id;
}
public int getId() {
return id;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
**二、结构型模式**
1. **适配器模式**:
- 设计思想:将某个类的接口转换成客户端期望的另一个接口表示,以消除由于接口不匹配所造成的类的兼容性问题。它包括类的适配器模式(通过继承源类并实现目标接口来扩展功能)、对象的适配器模式(持有源类的实例来调用其方法以实现目标接口)和接口的适配器模式(借助抽象类实现接口中的部分方法)。
- 应用场景:类的适配器模式适用于希望将一个类转换成满足另一个新接口的类的情况;对象的适配器模式适用于将一个对象转换成满足另一个新接口的对象的情况;接口的适配器模式适用于不希望实现接口中所有方法的情况。
interface Target {
void request();
}
class Adaptee {
public void specificRequest() {
System.out.println("Adaptee 的特定请求");
}
}
class Adapter extends Adaptee implements Target {
@Override
public void request() {
specificRequest();
}
}
2. **装饰模式**:
- 设计思想:给一个对象动态地添加一些新的功能,要求装饰对象和被装饰对象实现同一个接口,装饰对象持有被装饰对象的实例。
- 使用场景:需要扩展一个类的功能,并且能够动态地为对象增加或撤销功能时适用。但要注意该模式可能会产生过多相似的对象,导致不易排错。
interface Component {
void operation();
}
class ConcreteComponent implements Component {
@Override
public void operation() {
System.out.println("具体组件操作");
}
}
class Decorator implements Component {
protected Component component;
public Decorator(Component component) {
this.component = component;
}
@Override
public void operation() {
component.operation();
}
}
class ConcreteDecoratorA extends Decorator {
public ConcreteDecoratorA(Component component) {
super(component);
}
@Override
public void operation() {
System.out.println("装饰器 A 前操作");
super.operation();
System.out.println("装饰器 A 后操作");
}
}
class ConcreteDecoratorB extends Decorator {
public ConcreteDecoratorB(Component component) {
super(component);
}
@Override
public void operation() {
System.out.println("装饰器 B 前操作");
super.operation();
System.out.println("装饰器 B 后操作");
}
}
3. **代理模式**:
- 设计思想:引入一个代理类来替原对象进行一些操作,例如在租房子时找中介,或打官司时请律师。
- 使用场景:当已有的方法在使用时需要对原方法进行改进,且不想违反“对扩展开放,对修改关闭”的原则时,可以采用代理模式。通过代理类调用原有的方法,并对产生的结果进行控制,有助于将功能划分得更加清晰,方便后期维护。
interface Subject {
void request();
}
class RealSubject implements Subject {
@Override
public void request() {
System.out.println("真实主题请求");
}
}
class ProxySubject implements Subject {
private RealSubject realSubject;
public ProxySubject(RealSubject realSubject) {
this.realSubject = realSubject;
}
@Override
public void request() {
// 前置处理
System.out.println("代理前置处理");
realSubject.request();
// 后置处理
System.out.println("代理后置处理");
}
}
4. **外观模式**:
- 设计思想:为子系统中的一组不同功能接口提供一个统一的外观服务接口,降低类与类之间的耦合度。它将类与类之间的关系放在一个 facade 类中,使得子系统变得更加容易使用。
- 使用场景:当子系统变得越来越复杂时,可以使用外观模式为其提供一个简单的入口,以解决类与类之间的依赖关系,降低耦合度。
class SubSystemA {
public void operationA() {
System.out.println("子系统 A 操作");
}
}
class SubSystemB {
public void operationB() {
System.out.println("子系统 B 操作");
}
}
class Facade {
private SubSystemA subSystemA;
private SubSystemB subSystemB;
public Facade() {
subSystemA = new SubSystemA();
subSystemB = new SubSystemB();
}
public void doComplexOperation() {
subSystemA.operationA();
subSystemB.operationB();
}
}
5. **桥接模式**:
- 设计思想:将抽象化与实现化解耦,使得二者可以独立地变化。就像常用的 JDBC 桥 driverManager 一样,它提供了统一接口,每个数据库提供各自的实现,通过一个叫做数据库驱动的程序来桥接,从而在各个数据库之间进行切换时无需改动太多代码。
- 使用场景:例如在不同的操作系统平台上运行相同的软件,或者支持多种不同类型的数据库等情况。
interface Implementor {
void operationImpl();
}
class ConcreteImplementorA implements Implementor {
@Override
public void operationImpl() {
System.out.println("ConcreteImplementorA 的实现");
}
}
class ConcreteImplementorB implements Implementor {
@Override
public void operationImpl() {
System.out.println("ConcreteImplementorB 的实现");
}
}
abstract class Abstraction {
protected Implementor implementor;
public Abstraction(Implementor implementor) {
this.implementor = implementor;
}
public abstract void operation();
}
class RefinedAbstraction extends Abstraction {
public RefinedAbstraction(Implementor implementor) {
super(implementor);
}
@Override
public void operation() {
implementor.operationImpl();
}
}
6. **组合模式**:
- 设计思想:有时也叫部分-整体模式,将多个对象组合在一起进行操作,常用于表示树形结构,如二叉树等。在该模式中,组件节点和叶子节点都实现同一个基类接口,对组合对象的查询和访问通常是递归操作。
- 使用场景:适用于将多个对象组合成树形结构,以表示“整体-部分”的层次结构,使得用户对单个对象和组合对象的操作具有一致性的情况。
interface Component {
void operation();
}
class Leaf implements Component {
@Override
public void operation() {
System.out.println("叶子节点操作");
}
}
class Composite implements Component {
private List<Component> children = new ArrayList<>();
public void add(Component component) {
children.add(component);
}
public void remove(Component component) {
children.remove(component);
}
@Override
public void operation() {
for (Component component : children) {
component.operation();
}
}
}
7. **享元模式**:
- 设计思想:实现对象的共享,即共享池,当系统中对象数量较多时可以减少内存的开销,通常与工厂模式一起使用。
- 使用场景:例如数据库连接池,通过连接池的管理实现数据库连接的共享,避免每次重新创建连接,节省了数据库重新创建的开销,提升了系统的性能。
interface Flyweight {
void operation(String extrinsicState);
}
class ConcreteFlyweight implements Flyweight {
private String intrinsicState;
public ConcreteFlyweight(String intrinsicState) {
this.intrinsicState = intrinsicState;
}
@Override
public void operation(String extrinsicState) {
System.out.println("内在状态:" + intrinsicState + ",外在状态:" + extrinsicState);
}
}
class FlyweightFactory {
private Map<String, Flyweight> flyweights = new HashMap<>();
public Flyweight getFlyweight(String key) {
if (!flyweights.containsKey(key)) {
flyweights.put(key, new ConcreteFlyweight(key));
}
return flyweights.get(key);
}
}
**三、行为型模式**
1. **策略模式**:
- 设计思想:定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的变化不会影响到使用算法的客户。需要设计一个接口为一系列实现类提供统一的方法,多个实现类实现该接口,还可以设计一个抽象类(可有可无,属于辅助类)提供辅助函数。
- 使用场景:策略模式的决定权在用户,系统本身提供不同算法的实现,新增或删除算法时对各种算法进行封装。因此,该模式多用于算法决策系统中,外部用户只需决定使用哪个算法即可。
interface Strategy {
void execute();
}
class ConcreteStrategyA implements Strategy {
@Override
public void execute() {
System.out.println("策略 A
2. **模板方法模式**:
- 设计思想:将类中不变的行为移到父类中,去除子类中的重复代码。父类定义了算法的框架,而某些步骤的具体实现可以在子类中进行扩展或重写。
- 使用场景:适用于具有多个子类的情况,这些子类在执行某些操作时具有相似的流程,但具体的实现细节可能不同。
abstract class AbstractClass {
// 模板方法,定义算法骨架
public final void templateMethod() {
step1();
step2();
step3();
}
// 抽象方法,由子类实现
protected abstract void step1();
// 具体方法,子类可选择覆盖
protected void step2() {
System.out.println("AbstractClass: 默认的 step2 实现");
}
// 具体方法,子类不可覆盖
private final void step3() {
System.out.println("AbstractClass: 固定的 step3 实现");
}
}
class ConcreteClass extends AbstractClass {
@Override
protected void step1() {
System.out.println("ConcreteClass: 自定义的 step1 实现");
}
}
3. **观察者模式(发布-订阅模式)**:
- 设计思想:定义了一种一对多的关系,让多个观察者监听某一个对象,当该对象的状态发生改变时,会通知所有的观察者。
- 使用场景:在 MVC 框架模式中常用于实现模型(Model)和视图(View)的联动;也适用于其他需要在一个对象状态改变时通知多个相关对象的情况。
interface Observer {
void update(String message);
}
class ConcreteObserverA implements Observer {
@Override
public void update(String message) {
System.out.println("ConcreteObserverA 收到消息: " + message);
}
}
class ConcreteObserverB implements Observer {
@Override
public void update(String message) {
System.out.println("ConcreteObserverB 收到消息: " + message);
}
}
class Subject {
private List<Observer> observers = new ArrayList<>();
public void attach(Observer observer) {
observers.add(observer);
}
public void detach(Observer observer) {
observers.remove(observer);
}
public void notifyObservers(String message) {
for (Observer observer : observers) {
observer.update(message);
}
}
}
4. **迭代器模式**:
- 设计思想:提供一种顺序访问聚合对象(集合)中元素的方法,而无需暴露结构的底层表示和结构细节。遍历集合元素的任务从集合转移给了迭代器对象。
- 使用场景:当需要访问组合对象的内容,而又不想暴露其内部表示和结构时适用;迭代器可分为内部迭代器和外部迭代器,外部迭代器允许客户端更自由地使用,但需要熟悉组合对象的内部结构,而内部迭代器被封装在集合内部,在集合外部提供接口。
interface Iterator {
boolean hasNext();
Object next();
}
interface Collection {
Iterator iterator();
}
class ConcreteCollection implements Collection {
private Object[] items;
public ConcreteCollection(Object[] items) {
this.items = items;
}
@Override
public Iterator iterator() {
return new ConcreteIterator();
}
private class ConcreteIterator implements Iterator {
private int index = 0;
@Override
public boolean hasNext() {
return index < items.length;
}
@Override
public Object next() {
if (hasNext()) {
return items[index++];
}
return null;
}
}
}
5. **责任链模式**:
- 设计思想:让一组对象处理特定的请求,而对这个组中的成员(处理程序对象 handler)的增加、删除不影响组的完整性。链中的每一个对象实现同样的方法,处理对链中第一个对象发起的同一个请求。如果一个对象不知道如何处理这个请求,就把请求传给下一个响应器。
- 使用场景:适用于多个对象都有机会处理请求,并且请求的处理顺序或具体处理对象在运行时动态确定的情况。
interface Handler {
void handleRequest(String request);
}
class ConcreteHandlerA implements Handler {
private Handler nextHandler;
public ConcreteHandlerA(Handler nextHandler) {
this.nextHandler = nextHandler;
}
@Override
public void handleRequest(String request) {
if (request.equals("A")) {
System.out.println("ConcreteHandlerA 处理请求");
} else if (nextHandler!= null) {
nextHandler.handleRequest(request);
}
}
}
class ConcreteHandlerB implements Handler {
private Handler nextHandler;
public ConcreteHandlerB(Handler nextHandler) {
this.nextHandler = nextHandler;
}
@Override
public void handleRequest(String request) {
if (request.equals("B")) {
System.out.println("ConcreteHandlerB 处理请求");
} else if (nextHandler!= null) {
nextHandler.handleRequest(request);
}
}
}
6. **命令模式**:
- 设计思想:将请求封装成一个对象,从而使请求的发送者和接收者解耦。命令对象包含了请求的接收者以及执行请求的操作。
- 使用场景:例如在一个图形编辑器中,各种操作(如绘制图形、删除图形等)可以被封装成命令对象,通过执行这些命令对象来实现相应的操作;或者在需要记录、撤销/重做操作的系统中
interface Command {
void execute();
}
class ConcreteCommand implements Command {
private Receiver receiver;
public ConcreteCommand(Receiver receiver) {
this.receiver = receiver;
}
@Override
public void execute() {
receiver.action();
}
}
class Receiver {
public void action() {
System.out.println("接收者执行操作");
}
}
class Invoker {
private Command command;
public Invoker(Command command) {
this.command = command;
}
public void invoke() {
command.execute();
}
}