手记

Java之美[从菜鸟到高手演变]之设计模式

一、引言

(一)Java 设计模式的重要性

设计模式是软件工程中解决常见问题的最佳实践。它们提供了一种在特定情境下重用设计经验的方式,有助于提高代码的可维护性、可扩展性和可重用性。

(二)本系列博客的目的

本系列博客旨在帮助读者从基础到高级逐步掌握Java设计模式,通过理论与实践相结合的方式,使读者能够理解和应用这些设计模式,提升编程技能和解决复杂问题的能力。

二、设计模式简介

(一)设计模式的定义和分类

设计模式是在特定环境下,解决某一类重复出现的问题的通用解决方案。它们分为三类:创建型模式、结构型模式和行为型模式。

(二)常见的设计模式概述

- 创建型模式:涉及对象创建机制,试图以适当方式创建对象,隐藏创建逻辑,而不是直接实例化对象。

- 结构型模式:关注类和对象的组合,继承机制,用组合的方式来解决不同问题。

- 行为型模式:描述类或对象交互以及职责的分配。

三、从菜鸟到高手的演变

(一)菜鸟阶段:了解基本的设计原则

1. 单一职责原则:一个类应该只有一个引起它变化的原因。

2. 开放封闭原则:软件实体(类、模块、函数等)应该对扩展开放,对修改封闭。

3. 里氏替换原则:子类型必须能够替换掉它们的基类型。

4. 依赖倒置原则:高层模块不应该依赖于低层模块,两者都应该依赖其抽象。

5. 接口隔离原则:客户端不应该依赖它不需要的接口。

6. 迪米特法则:一个对象应该对其他对象保持最少的了解。

(二)进阶阶段:掌握常见的设计模式

1. 创建型模式

创建型模式主要关注对象的创建机制,目的是为了更灵活地创建对象,提高系统的灵活性和可维护性。下面我将详细解释每种创建型模式,并给出Java代码示例。

  • 单例模式(Singleton Pattern)

单例模式确保一个类只有一个实例,并提供一个全局访问点来访问这个实例。

Java代码示例:

public class Singleton {
    private static Singleton instance;
    private Singleton() {}
    public static synchronized Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}
  • 工厂模式(Factory Pattern)

工厂模式定义一个用于创建对象的接口,但是让子类决定实例化哪个类。工厂方法使一个类的实例化延迟到其子类。

Java代码示例:

interface Product {
    void use();
}
class ConcreteProductA implements Product {
    public void use() {
        System.out.println("Using Product A");
    }
}
class ConcreteProductB implements Product {
    public void use() {
        System.out.println("Using Product B");
    }
}
class Factory {
    public Product createProduct(String type) {
        if (type.equals("A")) {
            return new ConcreteProductA();
        } else if (type.equals("B")) {
            return new ConcreteProductB();
        }
        return null;
    }
}
  • 抽象工厂模式(Abstract Factory Pattern)

抽象工厂模式提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。

Java代码示例:

interface AbstractFactory {
    Product createProduct();
}
class ConcreteFactoryA implements AbstractFactory {
    public Product createProduct() {
        return new ConcreteProductA();
    }
}
class ConcreteFactoryB implements AbstractFactory {
    public Product createProduct() {
        return new ConcreteProductB();
    }
}
// Usage
AbstractFactory factory = new ConcreteFactoryA();
Product product = factory.createProduct();
product.use();
  • 建造者模式(Builder Pattern)

建造者模式将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

Java代码示例:

class Product {
    private String partA;
    private String partB;
    public void setPartA(String partA) {
        this.partA = partA;
    }
    public void setPartB(String partB) {
        this.partB = partB;
    }
    public void show() {
        System.out.println("Product Parts: " + partA + ", " + partB);
    }
}
class Builder {
    public void buildPartA() {}
    public void buildPartB() {}
    public Product getResult() {
        return new Product();
    }
}
class Director {
    public void construct(Builder builder) {
        builder.buildPartA();
        builder.buildPartB();
    }
}
  • 原型模式(Prototype Pattern)

原型模式用原型实例指定创建对象的种类,并且通过拷贝这些原型来创建新的对象。

Java代码示例:

import java.util.ArrayList;
import java.util.List;
class Prototype implements Cloneable {
    private List<String> list;
    public Prototype() {
        this.list = new ArrayList<>();
    }
    public void add(String item) {
        list.add(item);
    }
    public List<String> getList() {
        return list;
    }
    @Override
    public Prototype clone() {
        Prototype clone = new Prototype();
        clone.list = new ArrayList<>(this.list);
        return clone;
    }
}
// Usage
Prototype prototype = new Prototype();
prototype.add("Item 1");
Prototype clone = prototype.clone();
clone.add("Item 2");
System.out.println(prototype.getList()); // [Item 1]
System.out.println(clone.getList()); // [Item 1, Item 2]

2. 结构型模式

  • 适配器模式(Adapter Pattern)

适配器模式允许接口不兼容的类能够一起工作。它通过包装一个对象,使其表现出另一个对象的接口。

// 目标接口
interface Target {
    void request();
}
// 需要适配的类
class Adaptee {
    void specificRequest() {
        System.out.println("Adaptee's specific request");
    }
}
// 适配器
class Adapter implements Target {
    private Adaptee adaptee;
    public Adapter(Adaptee adaptee) {
        this.adaptee = adaptee;
    }
    public void request() {
        adaptee.specificRequest();
    }
}
// 使用适配器
public class AdapterExample {
    public static void main(String[] args) {
        Adaptee adaptee = new Adaptee();
        Target target = new Adapter(adaptee);
        target.request();
    }
}
  • 桥接模式(Bridge Pattern)

桥接模式将抽象部分与它的实现部分分离,使它们都可以独立地变化。

// 实现接口
interface Implementor {
    void operationImpl();
}
// 具体实现类
class ConcreteImplementorA implements Implementor {
    public void operationImpl() {
        System.out.println("ConcreteImplementorA operation");
    }
}
class ConcreteImplementorB implements Implementor {
    public void operationImpl() {
        System.out.println("ConcreteImplementorB operation");
    }
}
// 抽象类
abstract class Abstraction {
    protected Implementor implementor;
    public Abstraction(Implementor implementor) {
        this.implementor = implementor;
    }
    abstract void operation();
}
// 扩充抽象类
class RefinedAbstraction extends Abstraction {
    public RefinedAbstraction(Implementor implementor) {
        super(implementor);
    }
    public void operation() {
        implementor.operationImpl();
    }
}
// 使用桥接模式
public class BridgeExample {
    public static void main(String[] args) {
        Implementor implementorA = new ConcreteImplementorA();
        Abstraction abstraction = new RefinedAbstraction(implementorA);
        abstraction.operation();
    }
}
  • 组合模式(Composite Pattern)

组合模式允许你将对象组合成树形结构来表示“部分-整体”的层次结构。

import java.util.ArrayList;
import java.util.List;
// 组件
interface Component {
    void operation();
}
// 叶子
class Leaf implements Component {
    private String name;
    public Leaf(String name) {
        this.name = name;
    }
    public void operation() {
        System.out.println("Leaf " + name + " operation");
    }
}
// 组合
class Composite implements Component {
    private List<Component> children = new ArrayList<>();
    private String name;
    public Composite(String name) {
        this.name = name;
    }
    public void add(Component component) {
        children.add(component);
    }
    public void operation() {
        System.out.println("Composite " + name + " operation");
        for (Component component : children) {
            component.operation();
        }
    }
}
// 使用组合模式
public class CompositeExample {
    public static void main(String[] args) {
        Component leaf1 = new Leaf("Leaf1");
        Component leaf2 = new Leaf("Leaf2");
        Composite composite = new Composite("Composite1");
        composite.add(leaf1);
        composite.add(leaf2);
        composite.operation();
    }
}
  • 装饰模式(Decorator Pattern)

装饰模式动态地给一个对象添加一些额外的职责。

// 组件接口
interface Component {
    void operation();
}
// 具体组件
class ConcreteComponent implements Component {
    public void operation() {
        System.out.println("ConcreteComponent operation");
    }
}
// 装饰器
abstract class Decorator implements Component {
    protected Component component;
    public Decorator(Component component) {
        this.component = component;
    }
    public void operation() {
        component.operation();
    }
}
// 具体装饰器
class ConcreteDecoratorA extends Decorator {
    public ConcreteDecoratorA(Component component) {
        super(component);
    }
    public void operation() {
        super.operation();
        addedBehavior();
    }
    private void addedBehavior() {
        System.out.println("Added behavior from ConcreteDecoratorA");
    }
}
// 使用装饰模式
public class DecoratorExample {
    public static void main(String[] args) {
        Component component = new ConcreteComponent();
        component = new ConcreteDecoratorA(component);
        component.operation();
    }
}
  • 外观模式(Facade Pattern)

外观模式为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。

// 子系统类
class SubSystemA {
    public void methodA() {
        System.out.println("SubSystemA methodA");
    }
}
class SubSystemB {
    public void methodB() {
        System.out.println("SubSystemB methodB");
    }
}
// 外观类
class Facade {
    private SubSystemA systemA;
    private SubSystemB systemB;
    public Facade() {
        systemA = new SubSystemA();
        systemB = new SubSystemB();
    }
    public void method() {
        systemA.methodA();
        systemB.methodB();
    }
}
// 使用外观模式
public class FacadeExample {
    public static void main(String[] args) {
        Facade facade = new Facade();
        facade.method();
    }
}
  • 享元模式(Flyweight Pattern)

享元模式运用共享技术有效地支持大量细粒度的对象。

import java.util.HashMap;
import java.util.Map;
// 享元接口
interface Flyweight {
    void operation(String extrinsicState);
}
// 具体享元类
class ConcreteFlyweight implements Flyweight {
    private String intrinsicState;
    public ConcreteFlyweight(String intrinsicState) {
        this.intrinsicState = intrinsicState;
    }
    public void operation(String extrinsicState) {
        System.out.println("Intrinsic State = " + intrinsicState);
        System.out.println("Extrinsic State = " + extrinsicState);
    }
}
// 享元工厂
class FlyweightFactory {
    private Map<String, Flyweight> flyweights = new HashMap<>();
    public Flyweight getFlyweight(String key) {
        if (flyweights.containsKey(key)) {
            return flyweights.get(key);
        } else {
            Flyweight flyweight = new ConcreteFlyweight(key);
            flyweights.put(key, flyweight);
            return flyweight;
        }
    }
}
// 使用享元模式
public class FlyweightExample {
    public static void main(String[] args) {
        FlyweightFactory factory = new FlyweightFactory();
        Flyweight flyweight = factory.getFlyweight("key1");
        flyweight.operation("extrinsicState1");
    }
}
  • 代理模式(Proxy Pattern)

代理模式为其他对象提供一种代理以控制对这个对象的访问。

// 主题接口
interface Subject {
    void request();
}
// 真实主题
class RealSubject implements Subject {
    public void request() {
        System.out.println("RealSubject request");
    }
}
// 代理
class Proxy implements Subject {
    private RealSubject realSubject;
    public void request() {
        if (realSubject == null) {
            realSubject = new RealSubject();
        }
        preRequest();
        realSubject.request();
        postRequest();
    }
    private void preRequest() {
        System.out.println("Proxy preRequest");
    }
    private void postRequest() {
        System.out.println("Proxy postRequest");
    }
}
// 使用代理模式
public class ProxyExample {
    public static void main(String[] args) {
        Proxy proxy = new Proxy();
        proxy.request();
    }
}

3. 行为型模式

下面我将详细解释每种设计模式,并给出Java代码示例。

  • 责任链模式(Chain of Responsibility Pattern)

责任链模式允许你将请求沿着处理者链进行发送,直到有一个处理者处理它为止。

// 抽象处理者
abstract class Handler {
    protected Handler successor;
    public void setSuccessor(Handler successor) {
        this.successor = successor;
    }
    public abstract void handleRequest(int request);
}
// 具体处理者
class ConcreteHandler1 extends Handler {
    public void handleRequest(int request) {
        if (request >= 0 && request < 10) {
            System.out.println("ConcreteHandler1 handled the request");
        } else if (successor != null) {
            successor.handleRequest(request);
        }
    }
}
class ConcreteHandler2 extends Handler {
    public void handleRequest(int request) {
        if (request >= 10 && request < 20) {
            System.out.println("ConcreteHandler2 handled the request");
        } else if (successor != null) {
            successor.handleRequest(request);
        }
    }
}
  • 命令模式(Command Pattern)

命令模式将请求封装成对象,以便使用不同的请求、队列或者日志来参数化其他对象。

// 命令接口
interface Command {
    void execute();
}
// 具体命令
class ConcreteCommand implements Command {
    private Receiver receiver;
    ConcreteCommand(Receiver receiver) {
        this.receiver = receiver;
    }
    public void execute() {
        receiver.action();
    }
}
// 接收者
class Receiver {
    public void action() {
        System.out.println("Receiver action");
    }
}
// 调用者
class Invoker {
    private Command command;
    public void setCommand(Command command) {
        this.command = command;
    }
    public void executeCommand() {
        command.execute();
    }
}
  • 解释器模式(Interpreter Pattern)

解释器模式为语言创建解释器。

// 抽象表达式
interface Expression {
    boolean interpret(String context);
}
// 终结符表达式
class TerminalExpression implements Expression {
    private String data;
    public TerminalExpression(String data) {
        this.data = data;
    }
    public boolean interpret(String context) {
        return context.contains(data);
    }
}
// 非终结符表达式
class OrExpression implements Expression {
    private Expression expr1;
    private Expression expr2;
    public OrExpression(Expression expr1, Expression expr2) {
        this.expr1 = expr1;
        this.expr2 = expr2;
    }
    public boolean interpret(String context) {
        return expr1.interpret(context) || expr2.interpret(context);
    }
}
  • 迭代器模式(Iterator Pattern)

迭代器模式提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部表示。

import java.util.Iterator;
// 集合接口
interface Aggregate {
    Iterator createIterator();
}
// 具体集合
class ConcreteAggregate implements Aggregate {
    private Object[] items;
    public ConcreteAggregate() {
        items = new Object[10];
        // 初始化元素
    }
    public Iterator createIterator() {
        return new ConcreteIterator(this);
    }
    // 获取元素数量
    public int count() {
        return items.length;
    }
    // 获取特定位置的元素
    public Object get(int index) {
        return items[index];
    }
}
// 迭代器
class ConcreteIterator implements Iterator {
    private ConcreteAggregate aggregate;
    private int current;
    public ConcreteIterator(ConcreteAggregate aggregate) {
        this.aggregate = aggregate;
    }
    public boolean hasNext() {
        return current < aggregate.count() && aggregate.get(current) != null;
    }
    public Object next() {
        return aggregate.get(current++);
    }
}
  • 中介者模式(Mediator Pattern)

中介者模式定义了一个封装一组对象如何交互的对象。

// 中介者接口
interface Mediator {
    void send(String message, Colleague colleague);
}
// 具体中介者
class ConcreteMediator implements Mediator {
    private ConcreteColleague1 colleague1;
    private ConcreteColleague2 colleague2;
    public void setColleague1(ConcreteColleague1 colleague1) {
        this.colleague1 = colleague1;
    }
    public void setColleague2(ConcreteColleague2 colleague2) {
        this.colleague2 = colleague2;
    }
    public void send(String message, Colleague colleague) {
        if (colleague == colleague1) {
            colleague2.notify(message);
        } else {
            colleague1.notify(message);
        }
    }
}
// 同事类
abstract class Colleague {
    protected Mediator mediator;
    public Colleague(Mediator mediator) {
        this.mediator = mediator;
    }
    public abstract void send(String message);
    public abstract void notify(String message);
}
// 具体同事类
class ConcreteColleague1 extends Colleague {
    public ConcreteColleague1(Mediator mediator) {
        super(mediator);
    }
    public void send(String message) {
        mediator.send(message, this);
    }
    public void notify(String message) {
        System.out.println("Colleague1 gets message: " + message);
    }
}
  • 备忘录模式(Memento Pattern)

备忘录模式捕获一个对象的内部状态,并在该对象之外保存这个状态,以便之后恢复对象到先前的状态。

// 备忘录
class Memento {
    private String state;
    public Memento(String state) {
        this.state = state;
    }
    public String getState() {
        return state;
    }
}
// 发起人
class Originator {
    private String state;
    public void setState(String state) {
        this.state = state;
    }
    public String getState() {
        return state;
    }
    public Memento saveStateToMemento() {
        return new Memento(state);
    }
    public void getStateFromMemento(Memento memento) {
        state = memento.getState();
    }
}
// 管理者
class CareTaker {
    private List<Memento> mementoList = new ArrayList<Memento>();
    public void add(Memento state) {
        mementoList.add(state);
    }
    public Memento get(int index) {
        return mementoList.get(index);
    }
}
  • 观察者模式(Observer Pattern)

观察者模式定义了对象之间的一对多依赖,当一个对象状态改变时,它的所有依赖者都会收到通知并自动更新。

// 主题接口
interface Subject {
    void registerObserver(Observer observer);
    void removeObserver(Observer observer);
    void notifyObservers();
}
// 具体主题
class ConcreteSubject implements Subject {
    private List<Observer> observers = new ArrayList<>();
    private int state;
    public int getState() {
        return state;
    }
    public void setState(int state) {
        this.state = state;
        notifyObservers();
    }
    public void registerObserver(Observer observer) {
        observers.add(observer);
    }
    public void removeObserver(Observer observer) {
        observers.remove(observer);
    }
    public void notifyObservers() {
        for (Observer observer : observers) {
            observer.update();
        }
    }
}
// 观察者接口
interface Observer {
    void update();
}
// 具体观察者
class ConcreteObserver implements Observer {
    private ConcreteSubject subject;
    public ConcreteObserver(ConcreteSubject subject) {
        this.subject = subject;
        subject.registerObserver(this);
    }
    public void update() {
        System.out.println("Observer state updated: " + subject.getState());
    }
}
  • 状态模式(State Pattern)

状态模式允许一个对象在其内部状态改变时改变它的行为。

// 状态接口
interface State {
    void doAction(Context context);
}
// 具体状态
class StartState implements State {
    public void doAction(Context context) {
        System.out.println("Player is in start state");
        context.setState(this);
    }
    public String toString() {
        return "Start State";
    }
}
class StopState implements State {
    public void doAction(Context context) {
        System.out.println("Player is in stop state");
        context.setState(this);
    }
    public String toString() {
        return "Stop State";
    }
}
// 上下文
class Context {
    private State state;
    public Context() {
        state = null;
    }
    public void setState(State state) {
        this.state = state;
    }
    public State getState() {
        return state;
    }
}
  • 策略模式(Strategy Pattern)

策略模式定义了一系列算法,并将每个算法封装起来,使它们可以相互替换。

// 策略接口
interface Strategy {
    int doOperation(int num1, int num2);
}
// 具体策略
class OperationAdd implements Strategy {
    public int doOperation(int num1, int num2) {
        return num1 + num2;
    }
}
class OperationSubtract implements Strategy {
    public int doOperation(int num1, int num2) {
        return num1 - num2;
    }
}
// 上下文
class Context {
    private Strategy strategy;
    public Context(Strategy strategy) {
        this.strategy = strategy;
    }
    public int executeStrategy(int num1, int num2) {
        return strategy.doOperation(num1, num2);
    }
}
  • 模板方法模式(Template Method Pattern)

模板方法模式定义了一个算法的骨架,而将一些步骤延迟到子类中。

// 抽象类
abstract class Game {
    abstract void initialize();
    abstract void startPlay();
    abstract void endPlay();
    // 模板方法
    public final void play() {
        initialize();
        startPlay();
        endPlay();
    }
}
// 具体类
class Cricket extends Game {
    void initialize() {
        System.out.println("Cricket Game Initialized! Start playing.");
    }
    void startPlay() {
        System.out.println("Cricket Game Started. Enjoy the game!");
    }
    void endPlay() {
        System.out.println("Cricket Game Finished!");
    }
}
  • 访问者模式(Visitor Pattern)

它允许你在不修改已有代码的情况下定义新的操作。这种模式的基本思想是将数据结构和对数据结构的操作分离开来,使得对数据结构的操作可以独立于数据结构本身进行扩展和修改。

在访问者模式中,通常有两个主要的组成部分:

1. 访问者(Visitor):定义了对每个具体元素(ConcreteElement)需要执行的操作。

2. 元素(Element):定义了一个接受访问者的方法,通常命名为accept。

以下是访问者模式的主要参与者:

- Visitor:声明了一个访问者可以访问的元素类型的访问操作。

- ConcreteVisitor:实现了Visitor接口,定义了对元素的具体操作。

- Element:定义了一个接受访问者的方法。

- ConcreteElement:实现了Element接口,具体元素类。

- ObjectStructure:能枚举它的元素,可以提供一个高层的接口以允许访问者访问它的元素。

下面是一个简单的Java代码示例,演示了访问者模式的使用:

// 访问者接口
interface Visitor {
    void visit(ConcreteElementA element);
    void visit(ConcreteElementB element);
}
// 具体访问者
class ConcreteVisitor implements Visitor {
    @Override
    public void visit(ConcreteElementA element) {
        System.out.println("ConcreteVisitor is visiting " + element.getClass().getSimpleName());
    }
    @Override
    public void visit(ConcreteElementB element) {
        System.out.println("ConcreteVisitor is visiting " + element.getClass().getSimpleName());
    }
}
// 元素接口
interface Element {
    void accept(Visitor visitor);
}
// 具体元素A
class ConcreteElementA implements Element {
    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
}
// 具体元素B
class ConcreteElementB implements Element {
    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
}
// 对象结构
class ObjectStructure {
    private List<Element> elements = new ArrayList<>();
    public void addElement(Element element) {
        elements.add(element);
    }
    public void accept(Visitor visitor) {
        for (Element element : elements) {
            element.accept(visitor);
        }
    }
}
// 使用访问者模式的客户端代码
public class VisitorPatternDemo {
    public static void main(String[] args) {
        ObjectStructure objectStructure = new ObjectStructure();
        objectStructure.addElement(new ConcreteElementA());
        objectStructure.addElement(new ConcreteElementB());
        Visitor visitor = new ConcreteVisitor();
        objectStructure.accept(visitor);
    }
}

在这个例子中,Visitor接口定义了访问者可以访问的元素类型,ConcreteVisitor实现了具体的访问操作。Element接口定义了接受访问者的方法,而ConcreteElementA和ConcreteElementB是具体的元素类。ObjectStructure类管理元素集合,并允许访问者访问这些元素。

客户端代码创建了一个ObjectStructure对象,添加了一些元素,并创建了一个ConcreteVisitor对象来访问这些元素。通过调用ObjectStructure的accept方法,访问者可以遍历并操作所有元素。

(三)高手阶段:灵活运用设计模式解决实际问题

1. 设计模式的组合使用:例如,使用工厂模式结合单例模式来管理资源。

2. 设计模式的优化和改进:根据实际项目需求,对现有设计模式进行优化,如改进单例模式的线程安全性。

3. 设计模式在项目中的应用案例分析:分析具体项目中如何应用设计模式,如使用观察者模式实现事件驱动系统。

四、总结

(一)设计模式的学习方法和建议

- 理论学习:理解每种设计模式的目的、结构和适用场景。

- 实践应用:通过编写代码来实践设计模式,加深理解。

- 案例分析:分析实际项目中设计模式的应用,学习如何解决实际问题。

(二)对读者的鼓励和期望

希望读者通过本系列博客的学习,能够掌握Java设计模式,并将其应用到实际开发中,不断提升自己的编程能力和解决问题的能力。

1人推荐
随时随地看视频
慕课网APP