23种设计模式

简介

目的:培养编程思想,培养编程思想,培养编程思想。

GoF设计模式(Gang of Four)的本质是对类的封装+继承+多态 ,以及类之间的关联+组合 的充分理解。目的:低耦合+复用+扩展+维护。

七大原则:

设计原则 一句话解释 目的
开闭原则(OCP) 对扩展开放,对修改关闭 提高可扩展性和可维护性
依赖倒置原则(DIP) 面向接口编程,高层和底层模块都依赖抽象 低耦合
单一职责原则(SRP) 控制类的粒度大小,一个类只干一种事情 可读性,可维护
接口隔离原则(ISP) 一个接口只干自己的事情 低耦合,高聚合
迪米特法则(LoD) 一个类保持对其他对象的最少了解 低耦合
里氏替换原则(LSP) 子类不修改父类的功能 继承体系的健壮性
合成复用原则(CRP) 使用组合或聚合实现代码复用,减少继承 减少过多的类

设计模式:5创建型模式、7结构型模式、11行为模式。

创建型模式:

  • 单例模式
  • 原型模式
  • 工厂模式
  • 抽象工厂
  • 建造者模式

结构型模式:

  • 代理模式:
  • 适配器模式:
  • 桥接模式:
  • 装饰模式:
  • 外观模式:
  • 享元模式:
  • 组合模式:

行为模式:

  • 模板模式:
  • 策略模式:
  • 命令模式:
  • 状态模式:
  • 观察者模式:
  • 中介者模式:
  • 迭代器模式:
  • 访问者模式:
  • 备忘录模式:
  • 解释器模式:

开闭原则

OCP(Open-Closed Principle):对扩展开发,对修改关闭。

反例:

java 复制代码
// 如果新增图形,则需要修改此类,不符合OCP
public class GraphicEditor {
    public void draw(Shape shape) {
        if (shape.type == 1){
            drawTriangle();
        } else if (shape.type == 2) {
            drawRectangle();
        }
    }
    public void drawTriangle(){
        System.out.println("drawTriangle ...");
    }
    public void drawRectangle(){
        System.out.println("drawRectangle ...");
    }

}
class Shape {
    int type;
}

举例:

java 复制代码
// 新增图形,此类则无需修改
public class GraphicEditor {
    public void draw(Shape shape) {
        shape.draw();
    }
}
abstract class  Shape {
    abstract void draw();
}
class TriangleShape extends Shape{
    @Override
    void draw() {
        System.out.println("drawTriangle ...");
    }
}
class RectangleShape extends Shape{
    @Override
    void draw() {
        System.out.println("drawRectangle ...");
    }
}

依赖倒置原则

DIP(Dependency Inversion Principle):高层不要依赖底层实现,最好依赖高层的抽象类/接口。

反例:

java 复制代码
class EmailSender {
    public void send(String message) {
        System.out.println("发送: " + message);
    }
}

class Notification {
    // 违反DIP,如果后期使用微信/SMS发送还需要修改此类
    private EmailSender emailSender = new EmailSender();
    public void sendMessage(String message) {
        emailSender.send(message);
    }
}

举例:

java 复制代码
// 抽象层
interface MessageSender{
    void send(String message);
}

class EmailSender implements MessageSender {
    public void send(String message) {
        System.out.println("Email 发送: " + message);
    }
}
class SmsSender implements MessageSender {
    public void send(String message) {
        System.out.println("Sms 发送: " + message);
    }
}

class Notification {
    // 符合DIP, 后面如果新增wechat的发送,也无需修改此类
    private MessageSender sender;

    public Notification(MessageSender sender) {
        this.sender = sender;
    }

    public void sendMessage(String message) {
        sender.send(message);
    }
}

tip:当继承抽象类和实现接口都可以的时候。什么时候使用抽象类,什么时候使用接口,比如说有公共的逻辑就是用抽象类?

java 复制代码
abstract class MessageSender {
    protected String senderName;

    // 此处都有公共逻辑,使用抽象类,反之最好使用接口。
    void log(String message) {
        System.out.println("正在发送:" + message);
    }

    abstract void send(String message);
}

单一职责原则

SRP(Single Responsibility Principle),每个类只负责一类逻辑。

反例:

java 复制代码
// 不同的职责不要放在一起。
class UserManager {
    public void addUser(String name) {	// 增删改查可以放到一起
        System.out.println("添加用户:" + name);
    }

    public void sendEmail(String email) { // 发送和接受可以放到一起
        System.out.println("发送邮件到:" + email);
    }

    public void generateReport() {
        System.out.println("生成用户报表");
    }
}

举例:

java 复制代码
// 每个类负责自己的事情,后期维护方便
class UserService {
    public void addUser(String name) {
        System.out.println("添加用户:" + name);
    }
}
class EmailService {
    public void sendEmail(String email) {
        System.out.println("发送邮件到:" + email);
    }
}
class ReportService {
    public void generateReport() {
        System.out.println("生成用户报表");
    }
}

// 高层模块统一协调
public class Main {
    public static void main(String[] args) {
        UserService userService = new UserService();
        EmailService emailService = new EmailService();
        ReportService reportService = new ReportService();

        userService.addUser("张三");
        emailService.sendEmail("zhangsan@example.com");
        reportService.generateReport();
    }
}

接口隔离原则

ISP(Interface Segregation Principle):每个接口只负责同类的方法。不要把不相关抽象方法都放到一个接口中

反例:

java 复制代码
interface Animal {
    void eat();
    void fly();
    void swim();
}

class Bird implements Animal {
    public void eat() { System.out.println("鸟吃虫子"); }
    public void fly() { System.out.println("鸟会飞"); }
    public void swim() { /* 鸟不会游泳,但被迫实现 */ }
}

class Fish implements Animal {
    public void eat() { System.out.println("鱼吃水草"); }
    public void fly() { /* 鱼不会飞,但被迫实现 */ }
    public void swim() { System.out.println("鱼会游泳"); }
}

举例:

java 复制代码
interface Eatable {void eat();}
interface Flyable {void fly();}
interface Swimmable {void swim();}

// 接口按需实现
class Bird implements Eatable, Flyable {
    public void eat() { System.out.println("鸟吃虫子"); }
    public void fly() { System.out.println("鸟会飞"); }
}

class Fish implements Eatable, Swimmable {
    public void eat() { System.out.println("鱼吃水草"); }
    public void swim() { System.out.println("鱼会游泳"); }
}

迪米特法则

LoD(Law of Demeter):最少知道原则,不和陌生类交流

反例:

java 复制代码
class Student {
    public void study() {
        System.out.println("学生在学习");
    }
}

class Teacher {
    private Student student = new Student();
    public Student getStudent() {
        return student;
    }
}

class School {
    private Teacher teacher = new Teacher();

    public void startClass() {
        // ❌ School 直接访问了 Teacher 内部的 Student, 
        // 如果后期修改Teacher则此类也要修改
        teacher.getStudent().study();
    }
}

举例:

java 复制代码
class Student {
    public void study() {
        System.out.println("学生在学习");
    }
}

class Teacher {
    private Student student = new Student();

    // 由 Teacher 内部控制 Student 的行为
    public void teach() {
        student.study();
    }
}

class School {
    private Teacher teacher = new Teacher();

    public void startClass() {
        // ✅ 只和 Teacher 交互,不直接操作 Student
        teacher.teach();
    }
}

里氏替换原则

LSP(Liskov Substitution Principle):子类必须完全继承父类的特征,不能破坏父类的方法含义。否则使用接口或者抽象类

反例:

java 复制代码
class Rectangle {
    protected int width;
    protected int height;

    public void setWidth(int width) { this.width = width; }
    public void setHeight(int height) { this.height = height; }

    public int getArea() { return width * height; }
}

class Square extends Rectangle {
    @Override
    public void setWidth(int width) {
        this.width = width;
        this.height = width; // 保证长宽相等
    }

    @Override
    public void setHeight(int height) {
        this.width = height; // 同步更新
        this.height = height;
    }
}

public class Main {
    public static void main(String[] args) {
        Rectangle rect = new Rectangle();
        rect.setWidth(5);
        rect.setHeight(10);
        System.out.println("矩形面积:" + rect.getArea()); // 50 ✅

        // 父类引用指向子类,造成错误
        Rectangle square = new Square();
        square.setWidth(5);
        square.setHeight(10);
        System.out.println("正方形面积:" + square.getArea()); // ❌ 期望 50,结果 100
    }
}

举例:

java 复制代码
// 如果开发人员要实现的子类和父类违反LSP,那就改继承为实现接口
interface Shape {
    int getArea();
}

class Rectangle implements Shape {
    protected int width;
    protected int height;

    public Rectangle(int width, int height) {
        this.width = width;
        this.height = height;
    }

    public int getArea() { return width * height; }
}

class Square implements Shape {
    protected int side;

    public Square(int side) {
        this.side = side;
    }

    public int getArea() { return side * side; }
}

public class Main {
    public static void main(String[] args) {
        Shape rect = new Rectangle(5, 10);
        Shape square = new Square(5);

        System.out.println("矩形面积:" + rect.getArea());
        System.out.println("正方形面积:" + square.getArea());
    }
}

合成复用原则

CRP(Composite Reuse Principle):能使用组合或聚合就不要使用继承。继承(is-a)会让父子出现强耦合,组合(has-a)可以随时动态替换组件。

反例:

java 复制代码
class Printer {
    public void print(String content) {
        System.out.println("打印:" + content);
    }
}

// 如果Printer改变(比如输出方式不同),则此类必须要改
class MultiFunctionMachine extends Printer {
    public void scan(String content) {
        System.out.println("扫描:" + content);
    }
}

举例:

java 复制代码
class Printer {
    public void print(String content) {
        System.out.println("打印:" + content);
    }
}

class Scanner {
    public void scan(String content) {
        System.out.println("扫描:" + content);
    }
}

// ✅ 通过组合复用功能
class MultiFunctionMachine {
    private Printer printer = new Printer();
    private Scanner scanner = new Scanner();

    public void print(String content) {
        printer.print(content);
    }

    public void scan(String content) {
        scanner.scan(content);
    }
}

单例模式

唯一实例,

java 复制代码
// 1. 饿汉式
public class Hungry {
    private Hungry(){}
    private static Hungry hungry = new Hungry();
    public Hungry getInstance(){
        return hungry;
    }
}


// 2. DCL懒汉式
public class LazyMan {
    private LazyMan(){}
    // volatile: 防止实例化(非原子性操作)时指令重排,造成其他线程指向null
    private volatile static LazyMan lazyMan = null;
    // DCL双重检查锁
    public LazyMan getInstance(){
        if (lazyMan == null){
            synchronized (LazyMan.class){
                if (lazyMan == null){
                    lazyMan = new LazyMan(); // 非原子性操作
                    /**
                     * 1. 分配内存空间
                     * 2. 初始化对象
                     * 3. 对象指向这个空间
                     *
                     * 123 正常情况
                     * 132  A线程(CPU 指令重排)
                     *  此时B线程误以为对象非空(实际未初始化),所以有可能出错,需要volatile
                     */
                }
            }
        }
        return lazyMan;
    }
}


// 3. 静态内部类进行实例化
public class Holder {
    private Holder(){}

    public static Holder getInstance(){
        return Inner.HOLDER;
    }

    public static class Inner{
        public static final Holder HOLDER = new Holder();
    }
}

// 从调用来看都是,使用getInstance() 获取到实例
Singleton.getInstance();

单例可以通过反射进行破坏:

java 复制代码
public static void main(String[] args) throws Exception {
    Constructor<LazyMan> declaredConstructor = LazyMan.class.getDeclaredConstructor(null);
    declaredConstructor.setAccessible(true);
    LazyMan instance1 = declaredConstructor.newInstance(null);
    LazyMan instance2 = declaredConstructor.newInstance(null);
    System.out.println(instance1);
    System.out.println(instance2);
}

枚举的单例:

java 复制代码
// 通过枚举,即可防止反射破坏单例。
// 枚举本身也是类
public enum EnumSingleton {
    INSTANCE;
    public EnumSingleton getInstance(){
        return INSTANCE;
    }
    String name;
    int age;

    // 进行验证。
    public static void main(String[] args) throws Exception{
        Constructor<EnumSingleton> constructor =
                EnumSingleton.class.getDeclaredConstructor(String.class, int.class);
        constructor.setAccessible(true);
        EnumSingleton enumSingleton = constructor.newInstance("123",1234);
        System.out.println(enumSingleton);
    }
}

扩展:

bash 复制代码
# javap反编译, -p(private)把私有的也反编译
javap -p Hello.class
# jad, 更强大的反编译工具, -sjava(source java)把源文件class转为java
jad -sjava Hello.class

反编译的内容:

java 复制代码
public final class EnumSingleton extends Enum
{

    public static EnumSingleton[] values()
    {
        return (EnumSingleton[])$VALUES.clone();
    }

    public static EnumSingleton valueOf(String name)
    {
        return (EnumSingleton)Enum.valueOf(singleton/EnumSingleton, name);
    }

    private EnumSingleton(String s, int i)
    {
        super(s, i);
    }

    public EnumSingleton getInstance()
    {
        return INSTANCE;
    }

    public static void main(String args[])
        throws Exception
    {
        Constructor constructor = singleton/EnumSingleton.getConstructor(null);
        constructor.setAccessible(true);
        EnumSingleton enumSingleton = (EnumSingleton)constructor.newInstance(new Object[] {
            java/lang/String, Integer.TYPE
        });
        System.out.println(enumSingleton);
    }

    public static final EnumSingleton INSTANCE;
    private static final EnumSingleton $VALUES[];

    static 
    {
        INSTANCE = new EnumSingleton("INSTANCE", 0);
        $VALUES = (new EnumSingleton[] {
            INSTANCE
        });
    }
}

原型模式

prototype pattern,用Object的clone()方法实现。不过有浅克隆和深克隆之分。浅克隆默认不克隆引用对象,深克隆需要开发人员手动克隆引用对象

java 复制代码
public class Product implements Cloneable{
    private String name;
    private Date date;

    public Product(String name, Date date) {
        this.name = name;
        this.date = date;
    }

    public void setDate(Date date) {
        this.date = date;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    protected Object clone()  {
        try {
            // 实现深拷贝,否则克隆对象指向相同的引用字段
            Product clone = (Product)super.clone();
            clone.date = (Date)this.date.clone();
            return clone;
        } catch (CloneNotSupportedException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public String toString() {
        return "Product{" +
                "name='" + name + '\'' +
                ", date=" + date +
                '}';
    }
}


public class Consumer {
    public static void main(String[] args) {
        Date date = new Date();
        Product phone = new Product("Phone", date);
        // 开发人员手动克隆了Date对象,因此是深克隆
        Product phoneClone = (Product)phone.clone();
    }
}

工厂模式

简单工厂:通过一个工厂获取一类的的产品(实现共同的产品接口)。如果新增产品需要修改工厂的方法,违反开闭原则。

java 复制代码
// 抽象产品
interface Shape {
    void draw();
}

// 具体产品1
class Circle implements Shape {}
// 具体产品2
class Square implements Shape {}

// 工厂类:根据传入类型创建对象
class ShapeFactory {
    public static Shape createShape(String type) {
        if ("circle".equalsIgnoreCase(type)) {
            return new Circle();
        } else if ("square".equalsIgnoreCase(type)) {
            return new Square();
        } else {
            throw new IllegalArgumentException("未知图形类型: " + type);
        }
    }
}


public class SimpleFactoryDemo {
    public static void main(String[] args) {
        // 客户端无需关心对象创建逻辑,只需告诉工厂想要什么
        Shape shape1 = ShapeFactory.createShape("circle");
        shape1.draw();
        Shape shape2 = ShapeFactory.createShape("square");
        shape2.draw();
    }
}

工厂方法:每个产品都有对应的工厂。新增一个产品需要新增一个工厂。

java 复制代码
// 抽象产品
public interface Car {
    void name();
}

// 抽象工厂
public interface CarFactory {
    Car getCar();
}

// 具体产品
public class Audi implements Car {}
public class Tesla implements Car {}
// 具体工厂: 用于生产对应的具体产品
public class AudioFactory implements CarFactory{}
public class TeslaFactory implements CarFactory{}


public class Consumer {
    public static void main(String[] args) {
        // 通过不同的工厂获取对应的产品
        new AudioFactory().getCar();
        new TeslaFactory().getCar();
    }
}

抽象工厂

产品、工厂都为接口,一个工厂可以生产相同的产品族的产品。如果需要新增产品族,就建立对应的实现工厂接口的工厂无需修改接口。如果有新的产品等级才需要修改工厂接口

java 复制代码
// 抽象产品1
interface CPU {
    void run();
}

// 抽象产品2
interface GPU {
    void render();
}

// 抽象工厂
interface ComputerFactory {
    CPU createCPU();
    GPU createGPU();
}


// Intel 系列产品
class IntelCPU implements CPU {}
class IntelGPU implements GPU {}

// AMD 系列产品
class AMDCPU implements CPU {}
class AMDGPU implements GPU {}


// 具体工厂1
class IntelFactory implements ComputerFactory {
    @Override
    public CPU createCPU() {
        return new IntelCPU();
    }

    @Override
    public GPU createGPU() {
        return new IntelGPU();
    }
}

// 具体工厂2
class AMDFactory implements ComputerFactory {
    @Override
    public CPU createCPU() {
        return new AMDCPU();
    }

    @Override
    public GPU createGPU() {
        return new AMDGPU();
    }
}


public class AbstractFactoryDemo {
    public static void main(String[] args) {
        // 客户端选择哪家工厂,就得到一种产品族
        ComputerFactory intelFactory = new IntelFactory();
        CPU intelCpu = intelFactory.createCPU();
        GPU intelGpu = intelFactory.createGPU();
        intelCpu.run();
        intelGpu.render();


        ComputerFactory amdFactory = new AMDFactory();
        CPU amdCpu = amdFactory.createCPU();
        GPU amdGpu = amdFactory.createGPU();
        amdCpu.run();
        amdGpu.render();
    }
}

建造者模式

java 复制代码
public class Computer {
    private String cpu;
    private String ram;

    @Override
    public String toString() {
        return "Computer{" +
                "cpu='" + cpu + '\'' +
                ", ram='" + ram + '\'' +
                '}';
    }

    // 私有构造器,强制使用建造者模式
    private Computer(Builder builder) {
        this.cpu = builder.cpu;
        this.ram = builder.arm;
    }

    public static class Builder {
        private String cpu;
        private String arm;

        public Builder setCpu(String cpu) {
            this.cpu = cpu;
            return this;
        }

        public Builder setArm(String arm) {
            this.arm = arm;
            return this;
        }

        // 通过Builder 获取对应的产品
        public Computer build(){
            return new Computer(this);
        }
    }
}


public class Consumer {
    public static void main(String[] args) {
        Computer.Builder builder = new Computer.Builder()
                .setCpu("intel i9")
                .setArm("16 GB");
       	// 可以通过Builder获取多个对象
        Computer computer1 = builder.build();
        Computer computer2 = builder.build();
        System.out.println(computer1);
        System.out.println(computer2);
    }
}

适配器模式

把不同的接口适配成可以使用的接口

java 复制代码
// 目标的接口
public interface DC5 {
    int output5V();
}

// 被适配者
public class AC220 {
    public int output220V() {
        return 220;
    }
}

// 适配器
public class PowerAdapter implements DC5{
    private AC220 ac220;

    public PowerAdapter(AC220 ac220) {
        this.ac220 = ac220;
    }

    @Override
    public int output5V() {
        return ac220.output220V() / 44;
    }
}

public class Consumer {
    public static void main(String[] args) {
        // 通过适配器 转化需要的内容
        PowerAdapter powerAdapter = new PowerAdapter(new AC220());
        powerAdapter.output5V();
    }
}

桥接模式

在两个维度中扩展任意一个维度,不需要修改原有的系统,就像一座桥,把二者联合起来。场景:比如一个类有两个维度,而且需要对两个维度进行扩展。

java 复制代码
// 第一个维度:接口
public interface OSPlatform {
    void play(String fileName);
}
// 第二个维度:抽象类
public abstract class Video {
    protected OSPlatform platform;     // 桥接点
    public Video(OSPlatform platform) {
        this.platform = platform;
    }
    public abstract void play(String fileName);
}

// 第一个维度的A产品
public class WinPlatform implements OSPlatform{
    @Override
    public void play(String fileName) {
        System.out.println("WinPlatform: ");
    }
}
// 第一个维度的B产品
public class LinuxPlatform implements OSPlatform{
    @Override
    public void play(String fileName) {
        System.out.println("LinuxPlatform: ");
    }
}
// 第二个维度的X产品
public class LocalVideo extends Video{
    public LocalVideo(OSPlatform platform) {
        super(platform);
    }

    @Override
    public void play(String fileName) {
        System.out.println("LocalVideo: ");
        platform.play(fileName);
    }
}
// 第二个维度的Y产品
public class OnlineVideo extends Video{
    public OnlineVideo(OSPlatform platform) {
        super(platform);
    }
    @Override
    public void play(String fileName) {
        System.out.println("OnlineVideo: ");
        platform.play(fileName);
    }
}

public class Consumer {
    public static void main(String[] args) {
        Video video1 = new LocalVideo(new LinuxPlatform());
        video1.play("local.mp4");

        Video video2  = new OnlineVideo(new WinPlatform());
        video2.play("http://video.com/live");
    }
}

扩展:在桥接模式中,如果产生一个不匹配的产品,可以通过使用适配器模式,强行匹配。

代理模式

静态代理:开发人员写好代理和真实角色,然后客户进行使用。

java 复制代码
// 定义接口
public interface UserService {
    void login(String username, String password);
}

// 真实角色
public class UserServiceImpl implements UserService{
    @Override
    public void login(String username, String password) {
        System.out.println("登录成功:" + username + " " + password);
    }
}

// 代理角色
public class UserServiceProxy implements UserService{
    private UserServiceImpl userService;

    public UserServiceProxy(UserServiceImpl userService) {
        this.userService = userService;
    }

    @Override
    public void login(String username, String password) {
        if ("admin".equals(username)) {
            userService.login(username, password);
        } else {
            System.out.println("登录失败");
        }
    }
}

public class Consumer {
    public static void main(String[] args) {
        // 客户访问,通过代理实现
        UserServiceProxy proxy = new UserServiceProxy(new UserServiceImpl());
        proxy.login("admin", "123");
        proxy.login("guest", "123");
    }
}

动态代理:无需自己写代理,固定写法生成动态代理。

java 复制代码
// 接口
public interface UserService {
    void login(String username, String password);
    void register(String username, String password);
}

// 真实角色
public class UserServiceImpl implements UserService {
    @Override
    public void login(String username, String password) {
        System.out.println("登录成功:" + username);
    }

    @Override
    public void register(String username, String password) {
        System.out.println("注册成功:" + username);
    }
}

// 动态代理,固定写法
public class LogInvocationHandler implements InvocationHandler {
    private Object target;

    public LogInvocationHandler(Object object) {
        this.target = object;
    }

    // 也可以使用这种获取动态代理。
    public Object getProxy() {
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 动态代理的本质:就是使用反射
        Object result = method.invoke(target, args);
        return result;
    }
}


public class Consumer {
    public static void main(String[] args) {
        UserServiceImpl userService = new UserServiceImpl();
        // 方式1. 动态生成的代理, 只要任何对象接口都可以代理
        UserService proxy = (UserService) Proxy.newProxyInstance(
                userService.getClass().getClassLoader(),
                userService.getClass().getInterfaces(),
                new LogInvocationHandler(userService)
        );
        // 方式2. 也可以使用
        UserService proxy1 = (UserService) new LogInvocationHandler(userService).getProxy();

        proxy.login("admin", "123");
        proxy.register("guest", "123");
    }
}

装饰模式

场景:给对象增加扩展功能,但不修改类。

java 复制代码
// 抽象接口
public interface Coffee {
    int cost();
    String description();
}

// 接口的装饰类(抽象类)
public abstract class CoffeeDecorator implements Coffee {
    protected Coffee coffee;    // 持有被装饰的对象
    public CoffeeDecorator(Coffee coffee) {
        this.coffee = coffee;
    }
}

// 真实对象
public class SimpleCoffee implements Coffee{
    @Override
    public int cost() {
        return 10;
    }

    @Override
    public String description() {
        return "普通咖啡";
    }
}

// 装饰1
public class MilkDecorate extends CoffeeDecorator{
    public MilkDecorate(Coffee coffee) {
        super(coffee);
    }

    @Override
    public int cost() {
        return coffee.cost() + 2;
    }

    @Override
    public String description() {
        return coffee.description() + " + 牛奶";
    }
}

// 装饰2
public class SugarDecorate extends CoffeeDecorator{
    public SugarDecorate(Coffee coffee) {
        super(coffee);
    }

    @Override
    public int cost() {
        return coffee.cost() + 1;
    }

    @Override
    public String description() {
        return coffee.description() + " + 糖";
    }
}

public class Consumer {
    public static void main(String[] args) {
        Coffee coffee = new SimpleCoffee();
        coffee = new MilkDecorate(coffee);
        coffee = new SugarDecorate(coffee);
        // 输出:普通咖啡 + 牛奶 + 糖: 13
        System.out.println(coffee.description() + ": " + coffee.cost());
    }
}

外观模式

Facade Pattern,只需客户要调用外观类即可,不用关心各种各样的子系统

java 复制代码
// 各种各样的子系统
class DVDPlayer {
    void start() {System.out.println("DVDPlayer start");}
    void end() {System.out.println("DVDPlayer end");}
}
class SoundSystem {
    void start() {System.out.println("SoundSystem start");}
    void end() {System.out.println("SoundSystem end");}
}
class Light {
    void start() {System.out.println("Light start");}
    void end() {System.out.println("Light end");}
}

// 外观类
public class HomeTheaterFacade {
    private DVDPlayer dvdPlayer;
    private SoundSystem soundSystem;
    private Light light;

    public HomeTheaterFacade(DVDPlayer dvdPlayer, SoundSystem soundSystem, Light light) {
        this.dvdPlayer = dvdPlayer;
        this.soundSystem = soundSystem;
        this.light = light;
    }

    public void startMovie(){
        dvdPlayer.start();
        soundSystem.start();
        light.start();
    }
    public void endMovie(){
        dvdPlayer.end();
        soundSystem.end();
        light.end();
    }
}

public class Consumer {
    public static void main(String[] args) {
        HomeTheaterFacade homeTheaterFacade = new HomeTheaterFacade(new DVDPlayer(),
                new SoundSystem(),
                new Light());
        homeTheaterFacade.startMovie();
        homeTheaterFacade.endMovie();
    }
}

享元模式

Flyweight Pattern:内部状态共享,外部状态不共享

java 复制代码
// 抽象享元
public interface ChessPiece {
    void display(int x, int y);
}
// 具体享元
public class ConcreteChessPiece implements ChessPiece{
    private String color;
    public ConcreteChessPiece(String color) {
        this.color = color;
    }
    @Override
    public void display(int x, int y) {
        System.out.println(color + " " + x + " " +  y);
    }
}

// 享元工厂
public class ChessPieceFactory {
    // 内部状态,可以共享
    private HashMap<String, ChessPiece> map = new HashMap<>();
    public ChessPiece getChessPiece(String color) {
        if (!map.containsKey(color)){
            map.put(color, new ConcreteChessPiece(color));
        }
        return map.get(color);
    }
}


public class Consumer {
    public static void main(String[] args) {
        ChessPieceFactory factory = new ChessPieceFactory();
        // 二者相同,内部状态共享
        ChessPiece black1 = factory.getChessPiece("black");
        ChessPiece black2 = factory.getChessPiece("black");
        black1.display(1, 2);
        black2.display(3, 4);
    }
}

组合模式

Composite Pattern:用于把一组对象组织成树结构。叶子节点和容器节点对外提供相同的接口

举例:

java 复制代码
// 提供相同的抽象组件
public abstract class SystemNode {
    protected String name;
    public SystemNode(String name) {
        this.name = name;
    }
    abstract void display();
}

// 文件节点
public class FileNode extends SystemNode {
    public FileNode(String name) {
        super(name);
    }
    @Override
    void display() {
        System.out.println("fileNode: " + name);
    }
}

// 目录节点
public class DirectoryNode extends SystemNode {
    private List<SystemNode> list = new ArrayList<>();
    public DirectoryNode(String name) {
        super(name);
    }
    public void add(SystemNode node){
        list.add(node);
    }
    @Override
    void display() {
        for (SystemNode node : list) {
            // 父类引用指向子类,SystemNode node
            // 如果时子类DirectoryNode则继续递归,如果时FileNode则直接读取
            node.display();
        }
    }
}

public class Consumer {
    public static void main(String[] args) {
        DirectoryNode root = new DirectoryNode("root");
        DirectoryNode music = new DirectoryNode("music");
        DirectoryNode video = new DirectoryNode("video");

        FileNode song1 = new FileNode("稻香.mp3");
        FileNode song2 = new FileNode("稻香2.mp3");
        FileNode movie = new FileNode("盗梦空间.mp4");

        music.add(song1);
        music.add(song2);
        video.add(movie);
        root.add(music);
        root.add(video);
        root.display();
    }
}

模板模式

Template Method Pattern:定义一个算法骨架,将其他的一些方法延时到子类种实现。

java 复制代码
abstract class Beverage{
    // 定义固定的模板方法
    public final void prepareRecipe(){
        boilWater();
        brew();
        pourInCup();
    }
    private void boilWater() {
        System.out.println("烧水");
    }
    // 由子类实现
    protected abstract void brew();

    private void pourInCup() {
        System.out.println("倒入杯中");
    }
}

class Coffee extends Beverage{
    @Override
    protected void brew() {
        System.out.println("冲咖啡");
    }
}
class Tea extends Beverage{
    @Override
    protected void brew() {
        System.out.println("泡茶叶");
    }
}


public class Consumer {
    public static void main(String[] args) {
        Beverage coffee = new Coffee();
        Beverage tea = new Tea();
        // 不同子类,同样模板,
        coffee.prepareRecipe();
        tea.prepareRecipe();
    }
}

策略模式

Strategy Pattern:定义算法接口,实现具体的几种算法,然后通过替换不同的算法,进行策略的切换。

角色:策略接口、n个策略、上下文、客户端使用。

java 复制代码
// 策略接口
interface PaymentStrategy {
    void pay(double amount);
}

// 具体策略1
class WechatStrategy implements PaymentStrategy {
    @Override
    public void pay(double amount) {
        System.out.println("微信支付: " + amount );
    }
}
// 具体策略2
class AlipayStrategy implements PaymentStrategy {
    @Override
    public void pay(double amount) {
        System.out.println("支付宝支付: " + amount );
    }
}

// 上下文进行持有策略对象
class PaymentContext{
    private PaymentStrategy strategy;

    public void setStrategy(PaymentStrategy strategy) {
        this.strategy = strategy;
    }
    public void pay(double amount){
        strategy.pay(amount);
    }
}

public class Consumer {
    public static void main(String[] args) {
        PaymentContext paymentContext = new PaymentContext();
        // 同一上下文,通过不同的策略进行对应策略的方法
        paymentContext.setStrategy(new WechatStrategy());
        paymentContext.pay(10);
        paymentContext.setStrategy(new AlipayStrategy());
        paymentContext.pay(15);
    }
}

命令模式

Command Pattern:调用者和执行者解耦,封装成命令对象进行调用。

组成:抽象命令、接收者、n个具体命令、调用者、客户端。

java 复制代码
// 抽象命令
interface Command{
    void execute();
}

// 接收者
class Light{
    public void on(){
        System.out.println("灯开了");
    }
    public void off(){
        System.out.println("灯关了");
    }
}

// 开灯命令
class LightOnCommand implements Command{
    private Light light;
    public LightOnCommand(Light light) {
        this.light = light;
    }

    @Override
    public void execute() {
        light.on();
    }
}
// 关灯命令
class LightOffCommand implements Command{
    private Light light;
    public LightOffCommand(Light light) {
        this.light = light;
    }
    @Override
    public void execute() {
        light.off();
    }
}

// 调用者,调用不同的命令并执行
class RemoteControl {
    private Command command;
    public void setCommand(Command command) {
        this.command = command;
    }
    public void pressButton(){
        if (command != null)
            command.execute();
    }
}


public class Consumer {
    public static void main(String[] args) {
        Light light = new Light();
        LightOnCommand lightOnCommand = new LightOnCommand(light);
        LightOffCommand lightOffCommand = new LightOffCommand(light);
        RemoteControl remoteControl = new RemoteControl();

        // 调用者通过调用不同的命令,并执行
        remoteControl.setCommand(lightOnCommand);
        remoteControl.pressButton();
        remoteControl.setCommand(lightOffCommand);
        remoteControl.pressButton();
    }
}

状态模式

State Pattern:操作的对象Light具有状态对象,并且把对象Light的操作委托给状态进行操作。

java 复制代码
class Light{
    // 持有状态对象
    private LightState state;
    public Light(LightState state) {
        this.state = state;
    }
    public void setState(LightState state){
        this.state = state;
    }
    public void press(){
        state.pressSwtich(this);
    }
}

// 状态接口
interface LightState{
    void pressSwtich(Light light);
}
// 实现状态1
class LightOnState implements LightState{

    @Override
    public void pressSwtich(Light light) {
        System.out.println("灯关了");
        // 更新状态
        light.setState(new LightOffState());
    }
}
// 实现状态2
class LightOffState implements LightState{
    @Override
    public void pressSwtich(Light light) {
        System.out.println("灯开了");
        // 更新状态
        light.setState(new LightOnState());
    }
}


public class Consumer {
    public static void main(String[] args) {
        Light light = new Light(new LightOffState());
        light.press();  // 灯开了
        light.press();  // 灯关了
    }
}

观察者模式

java 复制代码
// 抽象观察者
interface Observer {
    void update(String message, float temperature);
}
// 具体观察者1
class PhoneDisplay implements Observer {
    private String name;
    public PhoneDisplay(String name) {
        this.name = name;
    }
    @Override
    public void update(String message, float temperature) {
        System.out.println(name + ", message:" + message + ", temperature:" + temperature);
    }
}
// 具体观察者2
class LargeScreenDisplay implements Observer {
    private String name;
    public LargeScreenDisplay(String name) {
        this.name = name;
    }
    @Override
    public void update(String message, float temperature) {
        System.out.println(name + ", message:" + message + ", temperature:" + temperature);
    }
}

// 抽象主题
interface Subject {
    void registerObserver(Observer observer);
    void removeObserver(Observer observer);
    void notifyObservers();
}
// 具体主题,
class WeatherState implements Subject {
    private String message;
    private float temperature;
    // 存储多个观察者
    private List<Observer> list = new ArrayList<>();

    @Override
    public void registerObserver(Observer observer) {
        list.add(observer);
    }

    @Override
    public void removeObserver(Observer observer) {
        list.remove(observer);
    }

    @Override
    public void notifyObservers() {
        for (Observer observer : list) {
            observer.update(message, temperature);
        }
    }

    public void setMeasurements(String message, float temperature) {
        this.message = message;
        this.temperature = temperature;
        notifyObservers();
    }
}


public class Consumer {
    public static void main(String[] args) {
        Observer tom = new PhoneDisplay("tom");
        Observer bob = new PhoneDisplay("bob");
        Observer jack = new LargeScreenDisplay("jack");

        WeatherState weatherState = new WeatherState();
        weatherState.registerObserver(tom);
        weatherState.registerObserver(bob);
        weatherState.registerObserver(jack);

        // 修改信息,之后自动会通知
        weatherState.setMeasurements("大风天气", 10);
        weatherState.setMeasurements("晴天", 20);
        /*
            tom, message:大风天气, temperature:10.0
            bob, message:大风天气, temperature:10.0
            jack, message:大风天气, temperature:10.0
            tom, message:晴天, temperature:20.0
            bob, message:晴天, temperature:20.0
            jack, message:晴天, temperature:20.0
         */
    }
}

中介者模式

Mediator Pattern:通过中介封装对象,然后中介操作对象进行执行任务。

java 复制代码
interface ChatRoomMediator{
    void showMessage(User user, String message);
}
class ChatRoom implements ChatRoomMediator{
    @Override
    public void showMessage(User user, String message) {
        System.out.println(user.getName() + " 发送了 " + message);
    }
}

abstract class User{
    protected String name;
    protected ChatRoomMediator mediator;
    public User(String name, ChatRoomMediator mediator) {
        this.name = name;
        this.mediator = mediator;
    }
    public String getName() {
        return name;
    }
    public abstract void send(String message);
}


class ConcreteUser extends User{
    public ConcreteUser(String name, ChatRoomMediator mediator) {
        super(name, mediator);
    }
    @Override
    public void send(String message) {
        mediator.showMessage(this, message);
    }
}

public class Consumer {
    public static void main(String[] args) {
        ChatRoomMediator mediator = new ChatRoom();
        ConcreteUser tom = new ConcreteUser("tom", mediator);
        ConcreteUser bob = new ConcreteUser("bob", mediator);
        ConcreteUser jack = new ConcreteUser("jack", mediator);

        tom.send("大家好");
        bob.send("你好");
        jack.send("今天周几");
    }
}

迭代器模式

Iterator Pattern:顺序访问集合内的元素,并且不暴露集合内部的元素。集合负责存储,迭代器负责遍历,客户端无需关心内部结构。

java 复制代码
// 抽象迭代器
interface Iterator<T>{
    boolean hasNext();
    T next();
}
// 抽象聚合
interface Collection<T>{
    void add(T item);
    Iterator<T> iterator();
}
// 具体聚合
class BookCollection implements Collection<String>{

    private int count = 0;
    private String[] books;

    public BookCollection(int size) {
        books = new String[size];
    }

    @Override
    public void add(String item) {
        if (count < books.length){
            books[count++] = item;
        }
    }

    @Override
    public Iterator<String> iterator() {
        return new BookIterator();
    }

    // 内部类:具体迭代器
    private class BookIterator implements Iterator<String> {
        private int index = 0;
        @Override
        public boolean hasNext() {
            return index < count;
        }

        @Override
        public String next() {
            if (hasNext()){
                return books[index++];
            }
            return null;
        }
    }
}


public class Consumer {
    public static void main(String[] args) {
        BookCollection collection = new BookCollection(3);
        collection.add("算法导论");
        collection.add("C语言");
        collection.add("Java语言");
        Iterator<String> iterator = collection.iterator();

        while (iterator.hasNext()){
            String item = iterator.next();
            System.out.println(item);
        }
    }
}

访问者模式

Visitor Pattern:一个对象由各个item组成,不同的访问者可以对各个item有不同的操作

java 复制代码
// 元素接口
interface ComputePart {
    void accept(ComputePartVistor vistor); // 接受访问者
}

// 访问者接口
interface ComputePartVistor {
    void visit(CPU cpu);
    void visit(Memory memory);
    void visit(Computer computer);
}

// 具体元素类1
class CPU implements ComputePart {
    @Override
    public void accept(ComputePartVistor vistor) {
        vistor.visit(this);
    }
}
// 具体元素类2
class Memory implements ComputePart {
    @Override
    public void accept(ComputePartVistor vistor) {
        vistor.visit(this);
    }
}
// 具体元素类3
class Computer implements ComputePart {
    ComputePart[] parts;

    public Computer() {
        parts = new ComputePart[]{new CPU(), new Memory()};
    }

    @Override
    public void accept(ComputePartVistor vistor) {
        for (ComputePart part : parts) {
            // 通过部件调用部件内部的 vistor.visit(this);
            part.accept(vistor);
        }
        vistor.visit(this);
    }
}

// 具体访问者1
class MaintenaceVistor implements ComputePartVistor{

    @Override
    public void visit(CPU cpu) {
        System.out.println("检查CPU");
    }

    @Override
    public void visit(Memory memory) {
        System.out.println("检查Memory");
    }

    @Override
    public void visit(Computer computer) {
        System.out.println("===检查电脑整体完成===");
    }
}
// 具体访问者2
class ReportVistor implements ComputePartVistor{

    @Override
    public void visit(CPU cpu) {
        System.out.println("CPU温度55°");
    }

    @Override
    public void visit(Memory memory) {
        System.out.println("Memory: 16GB");
    }

    @Override
    public void visit(Computer computer) {
        System.out.println("===整体电脑报告完成===");
    }
}

public class Consumer {
    public static void main(String[] args) {
        Computer computer = new Computer();
        // 生成对应的报告
        computer.accept(new MaintenaceVistor());
        computer.accept(new ReportVistor());
        /* 输出:
            检查CPU
            检查Memory
            ===检查电脑整体完成===
            CPU温度55°
            Memory: 16GB
            ===整体电脑报告完成===
         */
    }
}

备忘录模式

Memento Pattern:不破坏封装的前提下,获取一个对象的内部状态,并在对象之外进行保存;需要时再获取。

组成:备忘录(存储一次快照)、管理者(存储所有备忘录)、调用者(使用备忘录)、客户端

java 复制代码
// 用于保存的状态类
class Memento {
    private final String state;
    public Memento(String state) {
        this.state = state;
    }
    public String getState() {
        return state;
    }
}

// 存储状态类的类
class History {
    // 采用Vector用于保存各个快照
    private Stack<Memento> stack = new Stack<>();
    public void save(Memento memento) {
        stack.add(memento);
    }
    public Memento undo() {
        return stack.pop();
    }
}

// 调用者
class Editor {
    private String content;
    public String getContent() {
        return content;
    }
    public void setContent(String content) {
        this.content = content;
    }
    public Memento save() {	// 调用保存时,返回状态对象
        return new Memento(content);
    }
    public void restore(Memento memento) {
        this.content = memento.getState();
    }
}


public class Consumer {
    public static void main(String[] args) {
        Editor editor = new Editor();
        History history = new History();
        editor.setContent("第一次文本");
        history.save(editor.save());    // 保存快照
        editor.setContent("第二次文本");
        history.save(editor.save());    // 保存快照
        editor.setContent("第三次文本");

        System.out.println("当前: " + editor.getContent());
        editor.restore(history.undo()); // 取出快照
        System.out.println("取第一次: " + editor.getContent());
        editor.restore(history.undo()); // 取出快照
        System.out.println("取第二次: " + editor.getContent());
        /* 输出
            当前: 第三次文本
            取第一次: 第二次文本
            取第二次: 第一次文本 
         */
    }
}

解释器模式

Interpreter Pattern

举例

java 复制代码
// 抽象解释器
interface Express {
    int interpret();
}

// 基本表达式
class NumberExpress implements Express {
    private int value;
    public NumberExpress(int value) {
        this.value = value;
    }

    @Override
    public int interpret() {
        return value;
    }
}
// 具体表达式1
class AddExpress implements Express {
    private int leftValue;
    private int rightValue;

    public AddExpress(int leftValue, int rightValue) {
        this.leftValue = leftValue;
        this.rightValue = rightValue;
    }

    @Override
    public int interpret() {
        return leftValue + rightValue;
    }
}
// 具体表达式2
class SubtractExpress implements Express {
    private int leftValue;
    private int rightValue;

    public SubtractExpress(int leftValue, int rightValue) {
        this.leftValue = leftValue;
        this.rightValue = rightValue;
    }

    @Override
    public int interpret() {
        return leftValue - rightValue;
    }
}


public class Consumer {
    public static void main(String[] args) {
        String input = "2 + 3 - 4 + 5";
        System.out.println("结果: " + interpret(input)); // 结果: 6       
    }

    private static int interpret(String input) {
        String[] tokens = input.split(" ");
        Stack<Express> stack = new Stack<>();
        for (int i = 0; i < tokens.length; i++) {
            String token = tokens[i];
            if (token.equals("+")) {
                int rightValue = Integer.valueOf(tokens[++i]);
                int leftValue = stack.pop().interpret();
                stack.add(new AddExpress(leftValue, rightValue));
            } else if (token.equals("-")) {
                int rightValue = Integer.valueOf(tokens[++i]);
                int leftValue = stack.pop().interpret();
                stack.add(new SubtractExpress(leftValue, rightValue));
            } else {
                stack.add(new NumberExpress(Integer.valueOf(token)));
            }
        }
        return stack.pop().interpret();
    }
}
相关推荐
十五年专注C++开发3 小时前
QT 中的元对象系统(六):connect函数详解
开发语言·c++·qt·设计模式·系统架构·qevent
Deschen4 小时前
设计模式-适配器模式
java·设计模式·适配器模式
Asort7 小时前
JavaScript设计模式(十一):享元模式(Flyweight) - 优化内存与性能的利器
前端·javascript·设计模式
Asort7 小时前
JavaScript设计模式(十)——外观模式 (Facade)
前端·javascript·设计模式
余辉zmh8 小时前
【C++篇】:LogStorm——基于多设计模式下的同步&异步高性能日志库项目
开发语言·c++·设计模式
王嘉俊9258 小时前
设计模式--装饰器模式:动态扩展对象功能的优雅设计
java·设计模式·装饰器模式
Mr_WangAndy13 小时前
C++设计模式_结构型模式_组合模式Composite(树形模式)
c++·设计模式·组合模式
rongqing201914 小时前
Google 智能体设计模式:优先级排序
设计模式
Meteors.15 小时前
23种设计模式——享元模式(Flyweight Pattern)
设计模式·享元模式