设计模式的使用——建造者模式+适配器模式

news2024/11/28 0:35:45

项目代码地址

一、需求介绍

  现公司数据库有一张表中的数据,需要通过外部接口将数据推送到别人的系统中。现有的问题是:

  • 数据字段太多,而且双方系统实体字段不一致,每次都要通过get、set方法去对数据取值然后重新赋值。
  • 如果后期需要添加数据或者减少数据,修改不方便。

二、设计模式选择

  • 建造者模式(Builder):指将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的表示,这样的设计模式被称为建造者模式。它是将一个复杂的对象分解为多个简单的对象,然后一步一步构建而成。它将变与不变相分离,即产品的组成部分是不变的,但每一部分是可以灵活选择的。
  • 适配器模式(Adapter):将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。适配器模式分为类结构型模式和对象结构型模式两种,前者类之间的耦合度比后者高,且要求程序员了解现有组件库中的相关组件的内部结构,所以应用相对较少些。我们这里选择对象
      我们可以通过建造者模式去解决字段多且赋值困难问题,使用适配器模式去将我们系统的值转换为请求接口需要的值。

三、代码实现

1、准备实体类

  • 本地需要被转换的对象LocalEmployee.java,即适配者(Adaptee)类:它是被访问和适配的现存组件库中的组件接口。
package com.company.modeTest.dto;

public class LocalEmployee {

    private Integer id = 1;
    private String name = "我类个乖乖";
    private Integer age = 18;
    private Integer sex = 1;
    private String address;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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


    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Integer getSex() {
        return sex;
    }

    public void setSex(Integer sex) {
        this.sex = sex;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "Employee{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age='" + age + '\'' +
                ", sex=" + sex +
                ", address=" + address +
                '}';
    }
}

  • 远程接口需要的对象:RemoteEmployee.java、RemotePosition.java、RemoteRole.java
package com.company.modeTest.dto;

import java.util.List;

public class RemoteEmployee {

    private Integer remoteId;
    private String remoteName;
    private Integer remoteAge;
    private Integer remoteSex;
    private String remoteAddress;
    private List<RemoteRole> roles;
    private RemotePosition position;

    public List<RemoteRole> getRoles() {
        return roles;
    }

    public void setRoles(List<RemoteRole> roles) {
        this.roles = roles;
    }

    public RemotePosition getPosition() {
        return position;
    }

    public void setPosition(RemotePosition position) {
        this.position = position;
    }

    public Integer getRemoteId() {
        return remoteId;
    }

    public void setRemoteId(Integer remoteId) {
        this.remoteId = remoteId;
    }

    public String getRemoteName() {
        return remoteName;
    }

    public void setRemoteName(String remoteName) {
        this.remoteName = remoteName;
    }

    public Integer getRemoteAge() {
        return remoteAge;
    }

    public void setRemoteAge(Integer remoteAge) {
        this.remoteAge = remoteAge;
    }

    public Integer getRemoteSex() {
        return remoteSex;
    }

    public void setRemoteSex(Integer remoteSex) {
        this.remoteSex = remoteSex;
    }

    public String getRemoteAddress() {
        return remoteAddress;
    }

    public void setRemoteAddress(String remoteAddress) {
        this.remoteAddress = remoteAddress;
    }

    @Override
    public String toString() {
        return "RemoteEmployee{" +
                "remoteId=" + remoteId +
                ", remoteName='" + remoteName + '\'' +
                ", remoteAge='" + remoteAge + '\'' +
                ", remoteSex=" + remoteSex +
                ", remoteAddress='" + remoteAddress + '\'' +
                ", roles=" + roles +
                ", position=" + position +
                '}';
    }
}
package com.company.modeTest.dto;

public class RemotePosition {
    private Integer positionId;
    private String positionName;

    public Integer getPositionId() {
        return positionId;
    }

    public void setPositionId(Integer positionId) {
        this.positionId = positionId;
    }

    public String getPositionName() {
        return positionName;
    }

    public void setPositionName(String positionName) {
        this.positionName = positionName;
    }

    @Override
    public String toString() {
        return "RemotePosition{" +
                "positionId=" + positionId +
                ", positionName='" + positionName + '\'' +
                '}';
    }
}
package com.company.modeTest.dto;

public class RemoteRole {
    private Integer roleId;
    private String roleName;

    public Integer getRoleId() {
        return roleId;
    }

    public void setRoleId(Integer roleId) {
        this.roleId = roleId;
    }

    public String getRoleName() {
        return roleName;
    }

    public void setRoleName(String roleName) {
        this.roleName = roleName;
    }

    @Override
    public String toString() {
        return "RemoteRole{" +
                "roleId=" + roleId +
                ", roleName='" + roleName + '\'' +
                '}';
    }
}

2、编写建造者模式代码

  • 抽象建造者(Builder):它是一个包含创建产品各个子部件的抽象方法的接口,通常还包含一个返回复杂产品的方法。
package com.company.modeTest.builder;

/**
 * 抽象建造者
 * @param <O> 要构建的对象
 */
public interface BaseBuilder<O> {
    O build();
}

  • 对抽象建造者增强
package com.company.modeTest.builder;

/**
 * 对抽象建造者进行功能增强,使其支持..and()...的链式编码风格
 * @param <O> 要构建的对象
 * @param <B> 被构建对象的具体建造者
 */
public abstract class AbstractParamBuilderAdapter<O,B extends BaseBuilder<O>> {

    private B builder;

    void setBuilder(B builder) {
        this.builder = builder;
    }

    protected final B getBuilder() {
        return builder;
    }

    public B and() {
        return getBuilder();
    }
}


  • 具体建造者
package com.company.modeTest.builder;

import com.company.modeTest.dto.RemoteEmployee;
import com.company.modeTest.dto.RemotePosition;

public class PositionBuilder extends AbstractParamBuilderAdapter<RemoteEmployee,EmployeeBuilder> implements BaseBuilder<RemotePosition>{
    private final RemotePosition remotePosition = new RemotePosition();

    public PositionBuilder positionId(Integer positionId){
        remotePosition.setPositionId(positionId);
        return this;
    }

    public PositionBuilder positionName(String positionName){
        remotePosition.setPositionName(positionName);
        return this;
    }
    @Override
    public RemotePosition build() {
        return remotePosition;
    }
}

package com.company.modeTest.builder;

import com.company.modeTest.dto.RemoteEmployee;
import com.company.modeTest.dto.RemoteRole;

public class RoleBuilder extends AbstractParamBuilderAdapter<RemoteEmployee,EmployeeBuilder> implements BaseBuilder<RemoteRole>{
    private final RemoteRole remoteRole = new RemoteRole();

    public RoleBuilder roleId(Integer roleId){
        remoteRole.setRoleId(roleId);
        return this;
    }

    public RoleBuilder roleName(String roleName){
        remoteRole.setRoleName(roleName);
        return this;
    }
    @Override
    public RemoteRole build() {
        return remoteRole;
    }
}

package com.company.modeTest.builder;

import com.company.modeTest.dto.RemoteEmployee;
import com.company.modeTest.dto.RemoteRole;
import java.util.ArrayList;
import java.util.List;

public class EmployeeBuilder implements BaseBuilder<RemoteEmployee>{
    private final RemoteEmployee remoteEmployee = new RemoteEmployee();
    private final List<RoleBuilder> roleBuilders = new ArrayList<>();
    private final List<RemoteRole> roles = new ArrayList<>();
    private PositionBuilder positionBuilder;

    public EmployeeBuilder remoteId(Integer remoteId){
        remoteEmployee.setRemoteId(remoteId);
        return this;
    }

    public EmployeeBuilder remoteName(String remoteName){
        remoteEmployee.setRemoteName(remoteName);
        return this;
    }

    public EmployeeBuilder remoteAge(Integer remoteAge){
        remoteEmployee.setRemoteAge(remoteAge);
        return this;
    }
    public EmployeeBuilder remoteSex(Integer remoteSex){
        remoteEmployee.setRemoteSex(remoteSex);
        return this;
    }
    public EmployeeBuilder remoteAddress(String remoteAddress){
        remoteEmployee.setRemoteAddress(remoteAddress);
        return this;
    }
    public RoleBuilder roles(){
        RoleBuilder roleBuilder = new RoleBuilder();
        roleBuilder.setBuilder(this);
        roleBuilders.add(roleBuilder);
        return roleBuilder;
    }
    public PositionBuilder position(){
        if (positionBuilder==null){
            positionBuilder = new PositionBuilder();
        }
        positionBuilder.setBuilder(this);
        return positionBuilder;
    }
    @Override
    public RemoteEmployee build() {
        if (positionBuilder!=null){
            remoteEmployee.setPosition(positionBuilder.build());
        }
        if (roleBuilders.size()>0){
            for (RoleBuilder roleBuilder : roleBuilders) {
                roles.add(roleBuilder.build());
            }
            remoteEmployee.setRoles(roles);
        }
        return remoteEmployee;
    }


}

3、编写适配器模式代码

  • 目标(Target)接口:当前系统业务所期待的接口,它可以是抽象类或接口。
package com.company.modeTest.adapter;

/**
 * 目标(Target)接口
 * @param <F> 所要适配的数据源
 * @param <T> 所要适配的对象,即需要的结果
 */
public interface Target<F,T> {

    T adaptData(F fromData);

}

  • 对把目标接口进行增强,暴露建造者,使用户可以自定义构建数据,无需了解底层代码
package com.company.modeTest.adapter;


import com.company.modeTest.builder.BaseBuilder;

/**
 * @param <D> 被构架你对象的建造者
 * @param <O> 被构建的对象
 * @param <F> 所要适配的数据源
 */
public abstract  class AbstractDataTarget<D extends BaseBuilder<O>,O,F> implements Target<F,O> ,BaseBuilder<O>{
    public D dataBuilder;

    public D addInfo(){
        return dataBuilder;
    }

    @Override
    public O build() {
        return dataBuilder.build();
    }
}

  • 适配器(Adapter)类:它是一个转换器,通过继承或引用适配者的对象,把适配者接口转换成目标接口,让客户按目标接口的格式访问适配者。在这里,我们调用建造者,对接口必须的数据数据进行转换,并返回接口所需数据对象。
package com.company.modeTest.adapter;

import com.company.modeTest.builder.EmployeeBuilder;
import com.company.modeTest.dto.LocalEmployee;
import com.company.modeTest.dto.RemoteEmployee;

public class EmployeeAdapter extends AbstractDataTarget<EmployeeBuilder, RemoteEmployee, LocalEmployee>{

    public EmployeeAdapter() {
        dataBuilder = new EmployeeBuilder();
    }

    @Override
    public RemoteEmployee adaptData(LocalEmployee fromData) {
        return dataBuilder
                .remoteId(fromData.getId())
                .remoteName(fromData.getName())
                .remoteAge(fromData.getAge())
                .remoteSex(fromData.getSex())
                .build();
    }
}

4、代码测试

package com.company.modeTest;

import com.company.modeTest.adapter.EmployeeAdapter;
import com.company.modeTest.dto.LocalEmployee;
import com.company.modeTest.dto.RemoteEmployee;
import org.junit.Test;

public class MainTest {

    @Test
    public void test(){
        LocalEmployee localEmployee = new LocalEmployee();
        System.out.println("本地原始数据localEmployee---->"+localEmployee);
        EmployeeAdapter employeeAdapter = new EmployeeAdapter();
        RemoteEmployee remoteEmployee  = employeeAdapter.adaptData(localEmployee);
        System.out.println("适配获取的远程接口需要的数据remoteEmployee---->"+remoteEmployee);
        System.out.println("=====================用户开始自定义添加额外信息========");
        employeeAdapter.addInfo()
                .remoteAddress("中国加拿大省美市英县日本村")
                .position()
                    .positionId(2)
                    .positionName("技师")
                .and()
                .roles()
                    .roleId(3)
                    .roleName("太太")
                .and()
                .build();
        System.out.println("用户添加额外信息后remoteEmployee--->"+remoteEmployee);
    }

}


测试结果:
image.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/952351.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

使用php实现微信登录其实并不难,可以简单地分为三步进行

使用php实现微信登录其实并不难&#xff0c;可以简单地分为三步进行。 第一步&#xff1a;用户同意授权&#xff0c;获取code //微信登录public function wxlogin(){$appid "";$secret "";$str"http://***.***.com/getToken";$redirect_uriu…

家政电子邮件营销怎么做?邮件营销的方案?

家政电子邮件营销的作用&#xff1f;企业如何利用营销邮件拓客&#xff1f; 随着科技的不断发展&#xff0c;家政服务行业也逐渐融入了电子邮件营销的方式&#xff0c;这为家政企业提供了与客户更紧密互动的机会。在本文中&#xff0c;我们将探讨家政电子邮件营销的几个关键步…

OLED透明屏显示技术:未来显示科技的领航者

OLED透明屏显示技术是一种创新性的显示技术&#xff0c;它的特殊性质使其成为未来显示科技的领航者。 OLED透明屏具有高对比度、快速响应时间、广视角和低功耗等优势&#xff0c;同时&#xff0c;其透明度、柔性和薄型设计使其成为创新设计的理想选择。 本文将深入探讨OLED透…

从零做软件开发项目系列之九——项目结项

前言 一个项目&#xff0c;经过前期的需求调研分析&#xff0c;软件设计&#xff0c;程序开发&#xff0c;软件测试、系统部署、试运行系统调试等过程&#xff0c;最后到了项目的验收阶段&#xff0c;也就是项目生命周期的最后一个阶段&#xff0c;即项目结项&#xff0c;它涉…

什么是浏览器缓存(browser caching)?如何使用HTTP头来控制缓存?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 浏览器缓存和HTTP头控制缓存⭐ HTTP头控制缓存1. Cache-Control2. Expires3. Last-Modified 和 If-Modified-Since4. ETag 和 If-None-Match ⭐ 缓存策略⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点击…

什么是同源策略(same-origin policy)?它对AJAX有什么影响?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 同源策略&#xff08;Same-Origin Policy&#xff09;与 AJAX 影响⭐ 同源策略的限制⭐ AJAX 请求受同源策略影响⭐ 跨域资源共享&#xff08;CORS&#xff09;⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记…

rrpc:实现熔断与限流

一、服务端的自我保护&#xff08;实现限流&#xff09; 为什么需要限流器&#xff1f; 我们先看服务端&#xff0c;举个例子&#xff0c;假如我们要发布一个 Rrpc 服务&#xff0c;作为服务端接收调用端发送过来的请求&#xff0c;这时服务端的某个节点负载压力过高了&#x…

ARM DIY(五)摄像头调试

前言 今天&#xff0c;就着摄像头的调试&#xff0c;从嵌入式工程师的角度&#xff0c;介绍如何从无到有&#xff0c;一步一步地调出一款设备。 摄像头型号&#xff1a;OV2640 开发步骤 分为 2 个阶段 5 个步骤 阶段一&#xff1a; 设备树、驱动、硬件 阶段二&#xff1a; 应…

多线程使用HashMap,HashMap和HashTable和ConcurrentHashMap区别(面试题常考),硬盘IO,顺便回顾volatile

一、回顾&#x1f49b; 谈谈volatile关键字用法 volatile能够保证内存可见性&#xff0c;会强制从主内存中读取数据&#xff0c;此时如果其他线程修改被volatile修饰的变量&#xff0c;可以第一时间读取到最新的值。 二、&#x1f499; HashMap线程不安全没有锁,HashTable线程…

二分搜索树(Java 实例代码)

目录 二分搜索树 一、概念及其介绍 二、适用说明 三、二分查找法过程图示 四、Java 实例代码 src/runoob/binary/BinarySearch.java 文件代码&#xff1a; 二分搜索树 一、概念及其介绍 二分搜索树&#xff08;英语&#xff1a;Binary Search Tree&#xff09;&#xff…

20.液体加载特效

效果 源码 <!doctype html> <html> <head><meta charset="utf-8"><title>Milk | Liquid Loader Animation</title><link rel="stylesheet" href="style.css"> </head> <body><div cl…

【Flutter】Flutter 使用 Equatable 简化对象比较

【Flutter】Flutter 使用 Equatable 简化对象比较 文章目录 一、前言二、Equatable 简介三、为什么需要 Equatable&#xff1f;四、如何使用 Equatable五、Equatable 的其他特性六、完整的业务代码示例七、总结 一、前言 在 Flutter 开发中&#xff0c;我们经常需要比较对象的…

Python基础以及代码

Python基础以及代码 1.第一个代码如下&#xff1a; # 项目&#xff1a;第一个项目 # 作者&#xff1a;Adair # 开放时间&#xff1a; 2023/8/15 21:52print("Hello,world!!")如图所示&#xff1a; 2.数字的代码如下&#xff1a; # 项目&#xff1a;演示第一个项…

什么是Web组件(Web Components)?它们有哪些主要特点?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ Web 组件&#xff08;Web Components&#xff09;⭐ Web 组件的主要特点1. 自定义元素&#xff08;Custom Elements&#xff09;2. Shadow DOM3. HTML 模板4. 封装性和重用性5. 生态系统6. 跨框架兼容性 ⭐ 写在最后 ⭐ 专栏简介 前端入门…

新能源技术是实现碳达峰碳中和的必然路径

在绿色经济发展的时代背景之下&#xff0c;光伏屋顶瓦顺势而生。集发电、环保功能于一体的光伏屋顶瓦&#xff0c;让每一栋建筑都能成为一座绿色发电站&#xff0c;实现建筑用电自给&#xff0c;有效降低建筑能耗&#xff0c;极大的推动生态建筑和生态城市的发展。 太阳能光伏瓦…

win10/11电脑中病毒后programdata文件夹不显示,其他文件夹不显示问题,文件夹存在不显示问题解决

首先出现这个问题确保是打开了显示隐藏文件夹 发现问题还是没有解决继续往下看 就是上边这个文件夹&#xff0c;我解决之前忘记截图了&#xff0c;这是解决后的图 这个文件夹是系统应用程序数据缓存文件夹&#xff0c;很重要 好多病毒就是优先隐藏此文件夹来监视系统数据&…

【洛谷算法题】B2005-字符三角形【入门1顺序结构】

&#x1f468;‍&#x1f4bb;博客主页&#xff1a;花无缺 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! 本文由 花无缺 原创 收录于专栏 【洛谷算法题】 文章目录 【洛谷算法题】B2005-字符三角形【入门1顺序结构】&#x1f30f;题目描述&#x1f30f;输入格式…

ChatGPT Prompting开发实战(三)

一、关于chaining prompts与CoT的比较 前面谈到的CoT的推理过程&#xff0c;可以比作是一次性就烹调好一顿大餐&#xff0c;那么接下来要说的“chaining prompts”&#xff0c;其背后的理念是分多次来完成这样一项复杂任务&#xff0c;每次只完成其中一步或者一个子任务。核心…

猜拳游戏小程序源码 大转盘积分游戏小程序源码 积分游戏小程序源码

简介&#xff1a; 猜拳游戏大转盘积分游戏小程序前端模板源码&#xff0c;一共五个静态页面&#xff0c;首页、任务列表、大转盘和猜拳等五个页面 图片&#xff1a;

计算数组中各元素的方差 忽略数组中所有的nan值 numpy.nanvar()

【小白从小学Python、C、Java】 【计算机等级考试500强双证书】 【Python-数据分析】 计算数组中各元素的方差 忽略数组中所有的nan值 numpy.nanvar() [太阳]选择题 请问关于以下代码最后输出结果的是&#xff1f; import numpy as np a np.array([1, np.nan, 3]) print("…