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

智能推荐

彻底扒光 通过智能路由器拆解看其本质-程序员宅基地

文章浏览阅读1.7k次。可以看到很多联发科的MT芯片摘自:https://net.zol.com.cn/531/5312999.html彻底扒光 通过智能路由器拆解看其本质2015-07-23 00:40:00[中关村在线 原创] 作者:陈赫|责编:白宁收藏文章 分享到 评论(24)关注智能路由器拆解的朋友们注意啦!我们已经将这五款产品彻底扒开,将主板的真容展现在了大家的眼前。网友们可以看见这些智能路由器主板的做工和用料,我们还为网友们展示了主要的电子元器件,供大家品评观赏。..._路由器拆解

Java--深入JDK和hotspot底层源码剖析Thread的run()、start()方法执行过程_jdk的源码hotspot跟jdk是分开的-程序员宅基地

文章浏览阅读2.1k次,点赞101次,收藏78次。【学习背景】今天主要是来了解Java线程Thread中的run()、start()两个方法的执行有哪些区别,会给出一个简单的测试代码样例,快速理解两者的区别,再从源码层面去追溯start()底层是如何最终调用Thread#run()方法的,个人觉得这样的学习不论对面试,还是实际编程来说都是比较有帮助的。进入正文~学习目录一、代码测试二、源码分析2.1 run()方法2.2 start()方法三、使用总结一、代码测试执行Thread的run()、start()方法的测试代码如下:public_jdk的源码hotspot跟jdk是分开的

透视俄乌网络战之一:数据擦除软件_俄乌网络战观察(一)-程序员宅基地

文章浏览阅读4.4k次,点赞90次,收藏85次。俄乌冲突中,各方势力通过数据擦除恶意软件破坏关键信息基础设施计算机的数据,达到深度致瘫的效果,同时窃取重要敏感信息。_俄乌网络战观察(一)

Maven私服仓库配置-Nexus详解_nexus maven-程序员宅基地

文章浏览阅读1.7w次,点赞23次,收藏139次。Maven 私服是一种特殊的Maven远程仓库,它是架设在局域网内的仓库服务,用来代理位于外部的远程仓库(中央仓库、其他远程公共仓库)。当然也并不是说私服只能建立在局域网,也有很多公司会直接把私服部署到公网,具体还是得看公司业务的性质是否是保密的等等,因为局域网的话只能在公司用,部署到公网的话员工在家里也可以办公使用。_nexus maven

基于AI的计算机视觉识别在Java项目中的使用 (四) —— 准备训练数据_java ocr ai识别训练-程序员宅基地

文章浏览阅读934次。我先用所有的样本数据对模型做几轮初步训练,让深度神经模型基本拟合(数万条记录的训练集,识别率到99%左右),具备初步的识别能力,这时的模型就是“直男”。相较于训练很多轮、拟合程度很高的“油腻男”,它的拟合程度较低,还是“直男愣头青”。..............._java ocr ai识别训练

hibernate 数据库类型 date没有时分秒解决_hibernate解析時間只有年月日沒有時分秒-程序员宅基地

文章浏览阅读688次。一、问题现象:  在数据库表中日期字段中存的日期光有年月日,没有时分秒。二、产生原因:三 解决办法   检查表的相应映射xml文件。 <property name="operateDate" type="Date">如果同上面所写,那问题出在 type类型上了正确写法 :<property name="operateDate" type="java.util..._hibernate解析時間只有年月日沒有時分秒

随便推点

springbbot运行无法编译成功,找不到jar包报错:Error:(3, 46) java: 程序包org.springframework.context.annotation不存在-程序员宅基地

文章浏览阅读1k次,点赞2次,收藏2次。文章目录问题描述:解决方案:问题描述:提示:idea springbbot运行无法编译成功,找不到jar包报错E:\ideaProject\demokkkk\src\main\java\com\example\demo\config\WebSocketConfig.javaError:(3, 46) java: 程序包org.springframework.context.annotation不存在Error:(4, 46) java: 程序包org.springframework.conte_error:(3, 46) java: 程序包org.springframework.context.annotation不存在

react常见面试题_recate面试-程序员宅基地

文章浏览阅读6.4k次,点赞6次,收藏36次。1、redux中间件中间件提供第三方插件的模式,自定义拦截 action -&gt; reducer 的过程。变为 action -&gt; middlewares -&gt; reducer 。这种机制可以让我们改变数据流,实现如异步 action ,action 过滤,日志输出,异常报告等功能。常见的中间件:redux-logger:提供日志输出redux-thunk:处理异步操作..._recate面试

交叉编译jpeglib遇到的问题-程序员宅基地

文章浏览阅读405次。由于要在开发板中加载libjpeg,不能使用gcc编译的库文件给以使用,需要自己配置使用另外的编译器编译该库文件。/usr/bin/ld:.libs/jaricom.o:RelocationsingenericELF(EM:40)/usr/bin/ld:.libs/jaricom.o:RelocationsingenericELF(EM:40)...._jpeg_utils.lo: relocations in generic elf (em: 8) error adding symbols: file

【办公类-22-06】周计划系列(1)“信息窗” (2024年调整版本)-程序员宅基地

文章浏览阅读578次,点赞10次,收藏17次。【办公类-22-06】周计划系列(1)“信息窗” (2024年调整版本)

SEO优化_百度seo resetful-程序员宅基地

文章浏览阅读309次。SEO全称为Search Engine Optimization,中文解释为搜索引擎优化。一般指通过对网站内部调整优化及站外优化,使网站满足搜索引擎收录排名需求,在搜索引擎中提高关键词排名,从而把精准..._百度seo resetful

回归预测 | Matlab实现HPO-ELM猎食者算法优化极限学习机的数据回归预测_猎食者优化算法-程序员宅基地

文章浏览阅读438次。回归预测 | Matlab实现HPO-ELM猎食者算法优化极限学习机的数据回归预测_猎食者优化算法

推荐文章

热门文章

相关标签