Java中的设计模式在代码重构中的应用-程序员宅基地

技术标签: java  重构  设计模式  

设计模式是在软件开发中经常使用的一种经验总结,用于解决在特定上下文中重复出现的问题。在代码重构中,设计模式可以帮助我们改善代码的结构、可读性和可维护性。
下面是几个常见的设计模式及其在代码重构中的应用。

1. 单例模式(Singleton Pattern)

单例模式确保一个类仅有一个实例,并提供一个全局访问点。在重构中,如果某个类需要频繁创建和销毁对象,但又不希望存在多个实例,可以考虑使用单例模式。

重构前

public class Singleton {
    
    public static Singleton instance;

    public Singleton() {
    }

    public static Singleton getInstance() {
    
        if (instance == null) {
    
            instance = new Singleton();
        }
        return instance;
    }
}

重构后(线程安全):

public class Singleton {
    
    private static volatile Singleton instance;

    private Singleton() {
    }

    public static Singleton getInstance() {
    
        if (instance == null) {
    
            synchronized (Singleton.class) {
    
                if (instance == null) {
    
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

2. 工厂模式(Factory Pattern)

工厂模式用于创建对象,而无需指定创建对象的具体类。它隐藏了实例化对象的逻辑,使得代码更加灵活和易于维护。

重构前

public class Car {
    
    public Car() {
    
        System.out.println("Creating a car...");
    }
}

public class Client {
    
    public static void main(String[] args) {
    
        Car car = new Car();
    }
}

重构后

public interface Car {
    
    void drive();
}

public class SportsCar implements Car {
    
    @Override
    public void drive() {
    
        System.out.println("Driving a sports car...");
    }
}

public class SedanCar implements Car {
    
    @Override
    public void drive() {
    
        System.out.println("Driving a sedan car...");
    }
}

public class CarFactory {
    
    public static Car createCar(String type) {
    
        if ("sports".equalsIgnoreCase(type)) {
    
            return new SportsCar();
        } else if ("sedan".equalsIgnoreCase(type)) {
    
            return new SedanCar();
        } else {
    
            throw new IllegalArgumentException("Invalid car type: " + type);
        }
    }
}

public class Client {
    
    public static void main(String[] args) {
    
        Car sportsCar = CarFactory.createCar("sports");
        sportsCar.drive();
    }
}

3. 观察者模式(Observer Pattern)

观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。当主题对象状态发生变化时,它的所有依赖者(观察者)都会收到通知并自动更新。

重构前

假设有一个Subject类和一个Observer类,它们直接相互调用。

重构后

import java.util.ArrayList;
import java.util.List;

public interface Observer {
    
    void update(String message);
}

public class ConcreteObserver implements Observer {
    
    @Override
    public void update(String message) {
    
        System.out.println("Received message: " + message);
    }
}

public interface Subject {
    
    void registerObserver(Observer observer);
    void removeObserver(Observer observer);
    void notifyObservers(String message);
}

public class ConcreteSubject implements Subject {
    
    private List<Observer> observers = new ArrayList<>();

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

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

    @Override
    public void notifyObservers(String message) {
    
        for (Observer observer : observers) {
    
            observer.update(message);
        }
    }
}

public class Client {
    
    public static void main(String[] args) {
    
        ConcreteSubject subject = new ConcreteSubject();
        ConcreteObserver observer = new ConcreteObserver();

        subject.registerObserver(observer);
        subject.notifyObservers("Hello, observers!");
    }
}

这些只是设计模式在代码重构中的几个应用示例。设计模式的种类非常多,每一种模式都有其特定的应用场景和优势。在代码重构过程中,选择适合的设计模式可以帮助我们更好地组织代码,提高代码的可读性、可维护性和可扩展性。

4. 建造者模式(Builder Pattern)

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

重构前

public class Computer {
    
    private String ram;
    private String hdd;
    private String cpu;

    public Computer(String ram, String hdd, String cpu) {
    
        this.ram = ram;
        this.hdd = hdd;
        this.cpu = cpu;
    }

    // getters and setters
}

public class Client {
    
    public static void main(String[] args) {
    
        Computer computer = new Computer("4GB", "500GB", "Intel i5");
    }
}

重构后

public class Computer {
    
    private String ram;
    private String hdd;
    private String cpu;

    // private constructor to prevent direct instantiation
    private Computer(Builder builder) {
    
        this.ram = builder.ram;
        this.hdd = builder.hdd;
        this.cpu = builder.cpu;
    }

    public static class Builder {
    
        private String ram;
        private String hdd;
        private String cpu;

        public Builder setRam(String ram) {
    
            this.ram = ram;
            return this;
        }

        public Builder setHdd(String hdd) {
    
            this.hdd = hdd;
            return this;
        }

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

        public Computer build() {
    
            return new Computer(this);
        }
    }

    // getters
}

public class Client {
    
    public static void main(String[] args) {
    
        Computer computer = new Computer.Builder()
                .setRam("4GB")
                .setHdd("500GB")
                .setCpu("Intel i5")
                .build();
    }
}

5. 策略模式(Strategy Pattern)

策略模式定义了一系列可以互相替换的算法,使得算法可以独立于使用它的客户端变化。

重构前

假设有一个Sorter类,它根据不同的排序算法直接进行排序。

重构后

public interface SortingStrategy {
    
    void sort(int[] array);
}

public class BubbleSortStrategy implements SortingStrategy {
    
    @Override
    public void sort(int[] array) {
    
        // Bubble sort implementation
    }
}

public class QuickSortStrategy implements SortingStrategy {
    
    @Override
    public void sort(int[] array) {
    
        // Quick sort implementation
    }
}

public class Context {
    
    private SortingStrategy strategy;

    public Context(SortingStrategy strategy) {
    
        this.strategy = strategy;
    }

    public void setSortingStrategy(SortingStrategy strategy) {
    
        this.strategy = strategy;
    }

    public void sort(int[] array) {
    
        strategy.sort(array);
    }
}

public class Client {
    
    public static void main(String[] args) {
    
        Context context = new Context(new BubbleSortStrategy());
        int[] array = {
    5, 3, 8, 4, 2};
        context.sort(array);

        // Change sorting strategy
        context.setSortingStrategy(new QuickSortStrategy());
        context.sort(array);
    }
}

在以上示例中,我们使用了策略模式来将不同的排序算法与它们的使用者(Context类)解耦。这样,我们可以根据需要轻松地更改排序算法,而无需修改使用排序算法的代码。

这些只是设计模式在代码重构中的一些应用示例。在实际项目中,根据具体需求和问题,我们可以选择和应用不同的设计模式来解决复杂性和维护性问题。重要的是理解每种设计模式的原理和适用场景,并在重构过程中灵活应用它们来改进代码的质量和结构。

6. 原型模式(Prototype Pattern)

原型模式是一种创建型设计模式,它允许通过复制一个已存在的对象(原型)来创建新的对象,而不是重新实例化该类。这在创建对象成本较高或需要避免大量重复初始化时非常有用。

重构前

假设有一个复杂的对象ComplexObject,每次创建都需要进行大量的初始化工作。

public class ComplexObject {
    
    private String property1;
    private int property2;
    // ... 其他属性和方法

    public ComplexObject() {
    
        // 复杂的初始化过程
    }
}

public class Client {
    
    public static void main(String[] args) {
    
        ComplexObject obj1 = new ComplexObject();
        ComplexObject obj2 = new ComplexObject();
        // ... 重复创建多个对象
    }
}

重构后

public class ComplexObject implements Cloneable {
    
    private String property1;
    private int property2;
    // ... 其他属性和方法

    // 复制构造函数
    public ComplexObject(ComplexObject prototype) {
    
        this.property1 = prototype.property1;
        this.property2 = prototype.property2;
        // ... 复制其他属性
    }

    @Override
    public ComplexObject clone() {
    
        try {
    
            return new ComplexObject(this);
        } catch (CloneNotSupportedException e) {
    
            throw new Error("This shouldn't happen", e);
        }
    }

    // 其他方法
}

public class Client {
    
    public static void main(String[] args) {
    
        ComplexObject prototype = new ComplexObject();
        // 初始化原型对象

        ComplexObject obj1 = prototype.clone();
        ComplexObject obj2 = prototype.clone();
        // ... 通过克隆原型来创建多个对象
    }
}

7. 模板方法模式(Template Method Pattern)

模板方法模式定义了一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重新定义该算法的某些特定步骤。

重构前

有一个Game类,它包含多个步骤,但某些步骤的具体实现在不同类型的游戏中不同。

重构后

public abstract class Game {
    
    public final void play() {
    
        initializeGame();
        startGame();
        endGame();
    }

    protected abstract void initializeGame();
    protected abstract void startGame();
    protected abstract void endGame();
}

public class FootballGame extends Game {
    
    @Override
    protected void initializeGame() {
    
        // 初始化足球游戏
    }

    @Override
    protected void startGame() {
    
        // 开始足球游戏
    }

    @Override
    protected void endGame() {
    
        // 结束足球游戏
    }
}

public class BasketballGame extends Game {
    
    @Override
    protected void initializeGame() {
    
        // 初始化篮球游戏
    }

    @Override
    protected void startGame() {
    
        // 开始篮球游戏
    }

    @Override
    protected void endGame() {
    
        // 结束篮球游戏
    }
}

public class Client {
    
    public static void main(String[] args) {
    
        Game football = new FootballGame();
        football.play();

        Game basketball = new BasketballGame();
        basketball.play();
    }
}

在这个例子中,Game类定义了游戏的通用流程(play方法),而具体的初始化、开始和结束游戏的步骤则由子类(如FootballGameBasketballGame)来实现。这样,我们可以轻松地添加新的游戏类型,而无需改变游戏的整体结构。

8. 观察者模式(Observer Pattern)

观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。当主题对象状态发生变化时,它的所有依赖者(观察者)都会自动收到通知并更新。

重构前

当某个对象状态变化时,直接调用其他多个对象的更新方法。

重构后

public interface Observer {
    
    void update(String message);
}

public interface Subject {
    
    void registerObserver(Observer o);
    void removeObserver(Observer o);
    void notifyObservers();
    void setState(String state);
    String getState();
}

public class ConcreteSubject implements Subject {
    
    private List<Observer> observers;
    private String state;

    public ConcreteSubject() {
    
        this.observers = new ArrayList<>();
    }

    @Override
    public void registerObserver(Observer o) {
    
        observers.add(o);
    }

    @Override
    public void removeObserver(Observer o) {
    
        observers.remove(o);
    }

    @Override
    public void notifyObservers() {
    
        for (Observer observer : observers) {
    
            observer.update(state);
        }
    }

    @Override
    public void setState(String state) {
    
        this.state = state;
        notifyObservers();
    }

    @Override
    public String getState() {
    
        return state;
    }
}

public class ConcreteObserver implements Observer {
    
    private String name;
    private String subjectState;

    public ConcreteObserver(String name) {
    
        this.name = name;
    }

    @Override
    public void update(String message) {
    
        subjectState = message;
        display();
    }

    public void display() {
    
        System.out.println(name + " received: " + subjectState);
    }
}

public class Client {
    
    public static void main(String[] args) {
    
        Subject subject = new ConcreteSubject();
        Observer observer1 = new ConcreteObserver("Observer 1");
        Observer observer2 = new ConcreteObserver("Observer 2");

        subject.registerObserver(observer1);
        subject.registerObserver(observer2);

        subject.setState("New state");

        subject.removeObserver(observer1);
        subject.setState("Another state");
    }
}

在这个例子中,Subject是主题,它可以注册、注销观察者,并在状态变化时通知所有注册的观察者。Observer是观察者接口,定义了当主题状态变化时应该执行的操作。ConcreteSubjectConcreteObserver分别是主题和观察者的具体实现。当ConcreteSubject的状态变化时,它会调用notifyObservers方法,该方法会遍历所有注册的观察者并调用它们的update方法。这样,观察者就可以得到主题的最新状态并做出相应处理。

使用观察者模式的好处在于,它降低了主题和观察者之间的耦合度,使得它们可以独立地变化和复用。同时,它也提供了一种灵活的通知机制,使得多个观察者可以同时响应主题状态的变化。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/m0_37638307/article/details/138022955

智能推荐

linux devkmem 源码,linux dev/mem dev/kmem实现访问物理/虚拟内存-程序员宅基地

文章浏览阅读451次。dev/mem: 物理内存的全镜像。可以用来访问物理内存。/dev/kmem: kernel看到的虚拟内存的全镜像。可以用来访问kernel的内容。调试嵌入式Linux内核时,可能需要查看某个内核变量的值。/dev/kmem正好提供了访问内核虚拟内存的途径。现在的内核大都默认禁用了/dev/kmem,打开的方法是在 make menuconfig中选中 device drivers --> ..._dev/mem 源码实现

vxe-table 小众但功能齐全的vue表格组件-程序员宅基地

文章浏览阅读7.1k次,点赞2次,收藏19次。vxe-table,一个小众但功能齐全并支持excel操作的vue表格组件_vxe-table

(开发)bable - es6转码-程序员宅基地

文章浏览阅读62次。参考:http://www.ruanyifeng.com/blog/2016/01/babel.htmlBabelBabel是一个广泛使用的转码器,可以将ES6代码转为ES5代码,从而在现有环境执行// 转码前input.map(item => item + 1);// 转码后input.map(function (item) { return item..._让开发环境支持bable

FPGA 视频处理 FIFO 的典型应用_fpga 频分复用 视频-程序员宅基地

文章浏览阅读2.8k次,点赞6次,收藏29次。摘要:FPGA视频处理FIFO的典型应用,视频输入FIFO的作用,视频输出FIFO的作用,视频数据跨时钟域FIFO,视频缩放FIFO的作用_fpga 频分复用 视频

R语言:设置工作路径为当前文件存储路径_r语言设置工作目录到目标文件夹-程序员宅基地

文章浏览阅读575次。【代码】R语言:设置工作路径为当前文件存储路径。_r语言设置工作目录到目标文件夹

background 线性渐变-程序员宅基地

文章浏览阅读452次。格式:background: linear-gradient(direction, color-stop1, color-stop2, ...);<linear-gradient> = linear-gradient([ [ <angle> | to <side-or-corner>] ,]? &l..._background线性渐变

随便推点

【蓝桥杯省赛真题39】python输出最大的数 中小学青少年组蓝桥杯比赛 算法思维python编程省赛真题解析-程序员宅基地

文章浏览阅读1k次,点赞26次,收藏8次。第十三届蓝桥杯青少年组python编程省赛真题一、题目要求(注:input()输入函数的括号中不允许添加任何信息)1、编程实现给定一个正整数N,输出正整数N中各数位最大的那个数字。例如:N=132,则输出3。2、输入输出输入描述:只有一行,输入一个正整数N输出描述:只有一行,输出正整数N中各数位最大的那个数字输入样例:

网络协议的三要素-程序员宅基地

文章浏览阅读2.2k次。一个网络协议主要由以下三个要素组成:1.语法数据与控制信息的结构或格式,包括数据的组织方式、编码方式、信号电平的表示方式等。2.语义即需要发出何种控制信息,完成何种动作,以及做出何种应答,以实现数据交换的协调和差错处理。3.时序即事件实现顺序的详细说明,以实现速率匹配和排序。不完整理解:语法表示长什么样,语义表示能干什么,时序表示排序。转载于:https://blog.51cto.com/98..._网络协议三要素csdn

The Log: What every software engineer should know about real-time data's unifying abstraction-程序员宅基地

文章浏览阅读153次。主要的思想,将所有的系统都可以看作两部分,真正的数据log系统和各种各样的query engine所有的一致性由log系统来保证,其他各种query engine不需要考虑一致性,安全性,只需要不停的从log系统来同步数据,如果数据丢失或crash可以从log系统replay来恢复可以看出kafka系统在linkedin中的重要地位,不光是d..._the log: what every software engineer should know about real-time data's uni

《伟大是熬出来的》冯仑与年轻人闲话人生之一-程序员宅基地

文章浏览阅读746次。伟大是熬出来的  目录  前言  引言 时间熬成伟大:领导者要像狼一样坚忍   第一章 内圣外王——领导者的心态修炼  1. 天纵英才的自信心  2. 上天揽月的企图心  3. 誓不回头的决心  4. 宠辱不惊的平常心  5. 换位思考的同理心  6. 激情四射的热心  第二章 日清日高——领导者的高效能修炼  7. 积极主动,想到做到  8. 合理掌控自己的时间和生命  9. 制定目标,马..._当狼拖着受伤的右腿逃生时,右腿会成为前进的阻碍,它会毫不犹豫撕咬断自己的腿, 以

有源光缆AOC知识百科汇总-程序员宅基地

文章浏览阅读285次。在当今的大数据时代,人们对高速度和高带宽的需求越来越大,迫切希望有一种新型产品来作为高性能计算和数据中心的主要传输媒质,所以有源光缆(AOC)在这种环境下诞生了。有源光缆究竟是什么呢?应用在哪些领域,有什么优势呢?易天将为您解答!有源光缆(Active Optical Cables,简称AOC)是两端装有光收发器件的光纤线缆,主要构成部件分为光路和电路两部分。作为一种高性能计..._aoc 光缆

浏览器代理服务器自动配置脚本设置方法-程序员宅基地

文章浏览阅读2.2k次。在“桌面”上按快捷键“Ctrl+R”,调出“运行”窗口。接着,在“打开”后的输入框中输入“Gpedit.msc”。并按“确定”按钮。如下图 找到“用户配置”下的“Windows设置”下的“Internet Explorer 维护”的“连接”,双击选择“自动浏览器配置”。如下图 选择“自动启动配置”,并在下面的“自动代理URL”中填写相应的PAC文件地址。如下..._設置proxy腳本