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

智能推荐

240320俄罗斯方块java,JAVA游戏编程之三----j2me 手机游戏入门开发--俄罗斯方块_2-程序员宅基地

文章浏览阅读202次。packagecode;//importjava.awt.*;//importjava.awt.Canvas;//importjava.awt.event.*;//importjavax.swing.*;importjava.util.Random;importjavax.microedition.lcdui.*;//写界面所需要的包/***//***俄罗斯方块*高雷*2007年1..._240×320java游戏

在线电影院售票平台(源码+开题报告)-程序员宅基地

文章浏览阅读779次,点赞14次,收藏19次。然后,实现系统的数据管理和服务功能,包括用户的注册与登录、电影的分类与展示、电影信息的查询与推荐、座位的选择与预订、在线支付与电子票生成等。此外,随着在线视频平台的兴起,越来越多的人选择在线观看电影,这对传统电影院产生了巨大的冲击。研究意义: 开发在线电影院售票平台对于提升用户的观影体验、优化电影院的运营效率、促进电影产业的发展具有重要的意义。该系统旨在通过技术手段解决传统电影院售票中的问题,提供一个集成化的电影信息展示、座位选择、在线支付和用户评价平台,同时也为电影院和电影制作方提供有效的工具。

程序员熬夜写代码,用C/C++打造一个安全的即时聊天系统!_基于c++的即时聊天系统设计-程序员宅基地

文章浏览阅读509次。保护我们剩下的人的通话信息安全,使用TOX可以让你在和家人,朋友,爱人交流时保护你的隐私不受政府无孔不入的的偷窥.关于TOX:其他牛逼的软件因为一些细化服务问你要钱的时候, TOX分文不取 . 你用了TOX, 想干嘛就干嘛.网友评论:项目源码展示:源码测试效果:最后,如果你学C/C++编程有什么不懂的,可以来问问我哦,或许我能够..._基于c++的即时聊天系统设计

linux Java服务swap分区被占用内存泄露问题故障及解决方法_linux swap占用很高-程序员宅基地

文章浏览阅读584次。鱼弦:CSDN内容合伙人、CSDN新星导师、全栈领域创作新星创作者 、51CTO(Top红人+专家博主) 、github开源爱好者(go-zero源码二次开发、游戏后端架构 https://github.com/Peakchen)当Java服务在Linux系统中运行时,可能会出现swap分区被占用的内存泄露问题,导致系统性能下降或者崩溃。下面是该问题的故障及解决方法、底层结构、架构图、工作原理、使用场景详解和实际应用方式、原理详细描述、相关命令使用示例以及文献材料链接。_linux swap占用很高

word中利用宏替换标点标点全角与半角-程序员宅基地

文章浏览阅读662次。Alt+F11,然后插入-模块:复制下面代码到编辑窗口:Sub 半角标点符号转换为全角标点符号()'中英互译文档中将中文段落中的英文标点符号替换为中文标点符号 Dim i As Paragraph, ChineseInterpunction() As Variant, EnglishInterpunction() As Variant Dim MyRange..._替换半角宏

Android WebView使用总结_android webview真正加载完成-程序员宅基地

文章浏览阅读2.8k次。#.简介: WebView是Android提供的用来展示展示web页面的View,内部使用webkit浏览器引擎(一个轻量级的浏览器引擎),除了展示Web页面外,还可与Web页面内的JS脚本交互调用。WebView内部的WebSetting对象负责管理WebView的参数配置; WebViewClient负责处理WebView的各种请求和通知事件,在对应事件发生时会执行WebViewClient的对应回调; ChromeWebviewClient辅助Webview处理与JS一些交互......_android webview真正加载完成

随便推点

bitcoin 调试环境搭建-程序员宅基地

文章浏览阅读1.6k次。_bitcoin 调试环境搭建

曲线生成 | 图解B样条曲线生成原理(基本概念与节点生成算法)-程序员宅基地

文章浏览阅读4.3k次,点赞93次,收藏94次。为了解决贝塞尔曲线无法局部修正、控制性减弱、曲线次数过高、不易拼接的缺陷,引入B样条曲线(B-Spline)。本文介绍B样条曲线的基本概念:节点向量、支撑性、次数阶数、加权性质、节点生成算法等,为后续曲线计算打下基础。_样条曲线生成

CDH安装宝典之ClouderaManager_/opt/cloudera/cm-agent/service/mgmt/mgmt.sh: line -程序员宅基地

文章浏览阅读902次。配置本地repo库下载我的阿里云盘文件文件放置#创建目录mkdir -p /opt/cloudera/parcel-repo/mkdir -p /opt/cloudera/cm/yum install createrepoCDH 6.2.0 的三个文件放到/opt/cloudera/parcel-repo/中,并且注意把sha256后缀的文件名修改为sha#执行createrepo命令生成rpm元数据 最终/opt/cloudera/parcel-repo/会多一个repodata目录_/opt/cloudera/cm-agent/service/mgmt/mgmt.sh: line 76: /usr/java/jdk1.8.0_181

uni.canvasToTempFilePath在app正常,微信小程序报错: fail canvas is empty-程序员宅基地

文章浏览阅读943次,点赞2次,收藏2次。uni.canvasToTempFilePath_uni.canvastotempfilepath

SDRAM笔记_sdram 干扰-程序员宅基地

文章浏览阅读3.1k次。SRAM :静态RAM,不用刷新,速度可以非常快,像CPU内部的cache,都是静态RAM,缺点是一个内存单元需要的晶体管数量多,因而价格昂贵,容量不大。DRAM:动态RAM,需要刷新,容量大。SDRAM:同步动态RAM,需要刷新,速度较快,容量大。DDR SDRAM:双通道同步动态RAM,需要刷新,速度快,容量大。........................_sdram 干扰

Excel转SQL语句_excel数据怎么生成sql语句-程序员宅基地

文章浏览阅读7.3k次。假设表格有A、B、C、D四列数据,希望导入到你的数据库中表格table,对应的字段分别是col1、col2、col3、col4。_excel数据怎么生成sql语句

推荐文章

热门文章

相关标签