问:为何要用?
普通做法:
1.创建pojo
public class Person {
private String name;
private int age;
private double height;
private double weight;
public Person(String name) {
this.name = name;
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public Person(String name, int age, double height) {
this.name = name;
this.age = age;
this.height = height;
}
public Person(String name, int age, double height, double weight) {
this.name = name;
this.age = age;
this.height = height;
this.weight = weight;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public double getHeight() {
return height;
}
public void setHeight(double height) {
this.height = height;
}
public double getWeight() {
return weight;
}
public void setWeight(double weight) {
this.weight = weight;
}
}
2.创建对象
Person p1 = new Person();
Person p2 = new Person("张三");
Person p3 = new Person("李四", 18);
Person p4 = new Person("王五", 21, 180);
Person p5 = new Person("赵六", 17, 170, 65.4);
或者使用setName()、setWeight()等set方法
这样创建是没问题,
使用构造函数,前提是你自己很熟悉这个Person里面的参数顺序是什么,比如p4对象的21和180,抛开常理,这两个都是数字,你怎么知道那个是年龄那个是身高呢,这样就产生问题,如果数字类型的参数过多,那简直就是灾难,你自己都不知道每个数字代表什么,所以builder模式就很好解决了这个问题。
使用set方法,有可能导致对象不一致
构造模式的使用:
public class Person {
private String name;
private String sex;
private int age;
private int weight;
private int hight;
/**
* 带参构造
* @param name
* @param sex
* @param age
* @param weight
* @param hight
*/
public Person(String name, String sex, int age, int weight, int hight) {
super();
this.name = name;
this.sex = sex;
this.age = age;
this.weight = weight;
this.hight = hight;
}
/**
* getter和setter
* @return
*/
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
public int getHight() {
return hight;
}
public void setHight(int hight) {
this.hight = hight;
}
@Override
public String toString() {
return "Person [name=" + name + ", sex=" + sex + ", age=" + age + ", weight=" + weight + ", hight=" + hight
+ "]";
}
/**
* builder模式
*/
static class Builder {
private String name;
private String sex;
private int age;
private int weight;
private int hight;
public Builder name(String name) {
this.name = name;
return this;//返回自身对象,在后面的链式调用中就可以自身对象的属性和方法了
}
public Builder sex(String sex) {
this.sex = sex;
return this;//返回自身对象,在后面的链式调用中就可以自身对象的属性和方法了
}
public Builder age(int age) {
this.age = age;
return this;//返回自身对象,在后面的链式调用中就可以自身对象的属性和方法了
}
public Builder weight(int weight) {
this.weight = weight;
return this;//返回自身对象,在后面的链式调用中就可以自身对象的属性和方法了
}
public Builder hight(int hight) {
this.hight = hight;
return this;//返回自身对象,在后面的链式调用中就可以自身对象的属性和方法了
}
public Person build() {
return new Person(name, sex, age, weight, hight);
}
}
public static void main(String[] args) {
Person p1= new Person.Builder().age(18).hight(180).name("lx").build();
System.out.println(p1.toString());
}
这里注意一下几点基础知识:
1、类中的再声明一个类
java类里面还可以定义一个类,即内部类,但是要注意:1.内部类不能通过普通方式访问,内部类时外部类的一个普通成员,所以内部类可以方位外部类成员,即使这些类时private;2.若内部类声明成static时,就只能访问同样声明为static的外部类成员了。
2、只能有一个public 修饰的类(因为一个类文件中类名必须和文件名一致,而文件名根据规则必须是public修饰的那个类名)
做了这么多的铺垫,重点来了 ,build模式的应用场景在什么地方呢?
1、mybatis
mybatis四大核心,
SqlSessionFactoryBuilder、SqlSessionFactory、SqlSession、Mapper
1、SqlSessionFactoryBuilder
从命名上可以看出,这个是一个 Builder 模式的,用于创建 SqlSessionFactory 的类。SqlSessionFactoryBuilder 根据配置来构造 SqlSessionFactory。
2、SqlSessionFactory
SqlSessionFactory 顾名思义,是用于生产 SqlSession 的工厂。
通过如下的方式来获取 SqlSession 实例:
SqlSession session = sqlSessionFactory.openSession();
3、
SqlSession
SqlSession 包含了执行 SQL 的所有的方法(执行持久化的操作对象)。以下是示例:
SqlSession session = sqlSessionFactory.openSession();
try {
Blog blog = session.selectOne(
"org.mybatis.example.BlogMapper.selectBlog", 101);
} finally {
session.close();
}
当然,下面的方式可以做到类型安全:
SqlSession session = sqlSessionFactory.openSession();
try {
BlogMapper mapper = session.getMapper(BlogMapper.class);//面向接口编程
Blog blog = mapper.selectBlog(101);
} finally {
session.close();
}
4、
Mapper
Mapper 顾名思义,是用做 Java 与 SQL 之间的映射的。包括了 Java 映射为 SQL 语句,以及 SQL 返回结果映射为 Java。
比如,下面是一个常见的 Mapper 接口映射文件:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.mybatis.example.BlogMapper">
<select id="selectBlog" resultType="Blog">
select * from Blog where id = #{id}
</select>
</mapper>
其中 “org.mybatis.example.BlogMapper” 就是我们要射射的接口,selectBlog 就是BlogMapper上的方法。而这个 selectBlog 具体就是要执行“select * from Blog where id = #{id}”这个 SQL 语句。
这样,我们就能通过
Blog blog = session.selectOne(
"org.mybatis.example.BlogMapper.selectBlog", 101);
或者是
BlogMapper mapper = session.getMapper(BlogMapper.class);
Blog blog = mapper.selectBlog(101);
来获取到执行的结果。
当然,如果是采用注解的方式的话,可以省去 XML 文件:
public interface BlogMapper {
@Select("SELECT * FROM blog WHERE id = #{id}")
Blog selectBlog(int id);
}