总体来说,设计模式按照功能分为三类23种:
* 为什么要使用创建型设计模式?
** Student stu = new Student(//需要10个构造参数);
*** 有些时候,构建细节太多,其实程序员一点也不想去关心,所以可以直接将创建对象的事情交给专业的人士
*** 当一些类是通过第三方的jar包引用的,比如说BasicDataSource,我们基本上不了解如何去构造该对象。
* 设计模式的使用注意事项:
** 每个设计模式,都有自己的优缺点,我们要根据具体的实际情况,去进行选择合适的设计模式。
简单工厂
【只有一个工厂类】
public class SimpleFactory{
public Object getBean(String name){
if("cat".equals(name)){
return new Cat();
} else if("cow".equals(name)){
return new Cow();
}。。。。。。
}
}
工厂方法
【工厂会是多个,生产的产品是一个】,针对不同需求,可以创造不同的工厂,那问题是如何创建工厂呢?
和简单工厂不同的是:先有造工厂的方法(标准也叫接口),再根据标准去盖工厂,由这个工厂去创建不同的产品(产品在工厂方法中是抽象的)。
举例
SqlSessionFactory和DefaultSqlSessionFactory
SqlSessionFactory 接口(工厂标准)
public interface SqlSessionFactory {
SqlSession openSqlSession();
}
DefaultSqlSessionFactory 工厂去按照标准创建产品
public class DefaultSqlSessionFactory implements SqlSessionFactory {
// 我既然不负责Configuration的解析,那么我就需要被外部注入一个configuration
private Configuration configuration;
public DefaultSqlSessionFactory(Configuration configuration) {
this.configuration = configuration;
}
@Override
public SqlSession openSqlSession() {
return new DefaultSqlSession(configuration);
}
}
DefaultSqlSession 类 DefaultSqlSessionFactory是生产的产品,但是他也是实现了Sqlsession(标准)的产品
public class DefaultSqlSession implements SqlSession {
private Configuration configuration;
public DefaultSqlSession(Configuration configuration) {
this.configuration = configuration;
}
@SuppressWarnings("unchecked")
@Override
public <T> T selectOne(String statementId, Object param) {
List<Object> list = this.selectList(statementId, param);
if (list != null && list.size() == 1) {
return (T) list.get(0);
}
return null;
}
@SuppressWarnings("unchecked")
@Override
public <T> List<T> selectList(String statementId, Object param) {
MappedStatement mappedStatement = configuration.getMappedStatementById(statementId);
if (mappedStatement == null) {
return null;
}
try {
// TODO Executor executor = new CachingExecutor();
Executor executor = configuration.newExecutor();
return (List<T>) executor.query(configuration, mappedStatement, param, null);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@Override
public int insert(String statementId, Object param) {
// TODO Auto-generated method stub
return 0;
}
}
SqlSession 接口
public interface SqlSession {
<T> T selectOne(String statementId, Object param);
<T> List<T> selectList(String statementId, Object param);
int insert(String statementId, Object param);
}
优缺点
【工厂会是多个,生产的产品是多个,而这多个产品是属于一个产品族】,其他的都和工厂方法是一致的。
工厂模式区别
和工厂模式的对比
角色
举例a:创建Student
代码示例
StudentBuilder 构建者
public class StudentBuilder {
// 需要构建的对象
private Student student = new Student();
public StudentBuilder id(int id) {
student.setId(id);
return this;
}
public StudentBuilder name(String name) {
student.setName(name);
return this;
}
public StudentBuilder age(int age) {
student.setAge(age);
return this;
}
public StudentBuilder father(String fatherName) {
Father father = new Father();
father.setName(fatherName);
student.setFather(father);
return this;
}
// 构建对象
public Student build() {
return student;
}
}
BuildDemo 导演类
public class BuildDemo {
public static void main(String[] args) {
StudentBuilder builder = new StudentBuilder();
// 决定如何创建一个Student
builder.age(18).name("dili").father("wangjianlin");
//根据不同的表示去创建对象(私人定制)
Student student = builder.build();
//builder.build(xxxxxxxx).build();
System.out.println(student);
}
}
Student 产品类
public class Student {
private int id;
private String name;
private int age;
// 子产品
private Father father;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
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 Father getFather() {
return father;
}
public void setFather(Father father) {
this.father = father;
}
@Override
public String toString() {
return "Student [id=" + id + ", name=" + name + ", age=" + age + ", father=" + father + "]";
}
}
举例b:mybatis中的MappedStatement的内部类Builder
反思:
方式1:构建者模式 builder.username(“zhangsan”);
方式2:User user = new User(); user.setUsername(“zhangsan”);
区别在于
不通过new关键字,直接复制对象(不走构造方法,走的是底层的C函数调用JVM内存对象的复制功能)
原型对象,复制算法,我就可以搞出来一个和他一样的对象
两种实现方式
浅拷贝
/* 浅复制 */
public Object shallowClone() throws CloneNotSupportedException {
// super.clone()其实就是调用了Object对象的clone方法
// Object对象的clone方法是调用了native方法去在JVM中实现对象复制。
// 此时不会调用构造方法去创建对象
Prototype proto = (Prototype) super.clone();
return proto;
}
深拷贝
public Object deepClone() throws IOException, ClassNotFoundException {
/* 将对象序列化到二进制流 */
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);
/* 从二进制流中读出产生的新对象 */
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return ois.readObject();
}