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

项目代码地址

一、需求介绍

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

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

二、设计模式选择

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

三、代码实现

1、准备实体类

  • 本地需要被转换的对象LocalEmployee.java,即适配者(Adaptee)类:它是被访问和适配的现存组件库中的组件接口。
java 复制代码
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
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 +
                '}';
    }
}
java 复制代码
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 + '\'' +
                '}';
    }
}
java 复制代码
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):它是一个包含创建产品各个子部件的抽象方法的接口,通常还包含一个返回复杂产品的方法。
java 复制代码
package com.company.modeTest.builder;

/**
 * 抽象建造者
 * @param <O> 要构建的对象
 */
public interface BaseBuilder<O> {
    O build();
}
  • 对抽象建造者增强
java 复制代码
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();
    }
}
  • 具体建造者
java 复制代码
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;
    }
}
java 复制代码
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;
    }
}
java 复制代码
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)接口:当前系统业务所期待的接口,它可以是抽象类或接口。
java 复制代码
package com.company.modeTest.adapter;

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

    T adaptData(F fromData);

}
  • 对把目标接口进行增强,暴露建造者,使用户可以自定义构建数据,无需了解底层代码
java 复制代码
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)类:它是一个转换器,通过继承或引用适配者的对象,把适配者接口转换成目标接口,让客户按目标接口的格式访问适配者。在这里,我们调用建造者,对接口必须的数据数据进行转换,并返回接口所需数据对象。
java 复制代码
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、代码测试

java 复制代码
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);
    }

}

测试结果:

相关推荐
仙魁XAN1 小时前
Unity 设计模式 之 创造型模式-【工厂方法模式】【抽象工厂模式】
unity·设计模式·工厂方法模式·抽象工厂模式
龙哥·三年风水11 小时前
活动系统开发之采用设计模式与非设计模式的区别-后台功能总结
设计模式·php·tinkphp6
一头老羊12 小时前
前端常用的设计模式
设计模式
严文文-Chris13 小时前
【设计模式-组合】
设计模式
kimloner14 小时前
工厂模式(二):工厂方法模式
java·设计模式·工厂方法模式
丶白泽16 小时前
重修设计模式-结构型-桥接模式
java·设计模式·桥接模式
南郁17 小时前
把设计模式用起来!(3)用不好模式?之时机不对
设计模式
Lill_bin19 小时前
Lua编程语言简介与应用
开发语言·数据库·缓存·设计模式·性能优化·lua
瞅瞅水21 小时前
设计模式中工厂模式的C语言实现
设计模式
SchneeDuan1 天前
iOS六大设计原则&&设计模式
ios·设计模式·cocoa·设计原则