一、单例设计模式
单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。
1,单例模式的结构
单例模式的主要有以下角色:
单例类。只能创建一个实例的类
访问类。使用单例类
2,单例模式的实现
单例设计模式分类两种:
饿汉式:类加载就会导致该单实例对象被创建
懒汉式:类加载不会导致该单实例对象被创建,而是首次使用该对象时才会创建
2.1,饿汉式
2.1.1,静态变量方式
/**
* @Author zhou_ge
* @Date 2022/6/23 12:08
* @PackageName:xyz.zhouge.designPatterns.singleton.hungry.staticVar
* @ClassName: DataBase
* @Description: TODO
* @Version 1.0
*/
public class DataBase {
//私有构造方法
private DataBase(){}
//创建静态变量
private static DataBase connection = new DataBase();
//创建公共的静态获取变量方法
public static DataBase getConnection(){
return connection;
}
}
/**
* @Author zhou_ge
* @Date 2022/6/23 12:12
* @PackageName:xyz.zhouge.designPatterns.singleton.hungry.staticVar
* @ClassName: Client
* @Description: TODO
* @Version 1.0
*/
public class Client {
public static void main(String[] args) {
DataBase var1 = DataBase.getConnection();//实例1
DataBase var2 = DataBase.getConnection();//实例2
System.out.println(var1.equals(var2));
}
}
2.1.2,静态代码块方式
/**
* @Author zhou_ge
* @Date 2022/6/23 12:15
* @PackageName:xyz.zhouge.designPatterns.singleton.hungry.staticBlock
* @ClassName: DataBase
* @Description: TODO
* @Version 1.0
*/
public class DataBase {
private DataBase(){}
private static DataBase connection ;
static {
connection = new DataBase();
}
public static DataBase getConnection(){
return connection;
}
}
/**
* @Author zhou_ge
* @Date 2022/6/23 12:12
* @PackageName:xyz.zhouge.designPatterns.singleton.hungry.staticVar
* @ClassName: Client
* @Description: TODO
* @Version 1.0
*/
public class Client {
public static void main(String[] args) {
DataBase var1 = DataBase.getConnection();
DataBase var2 = DataBase.getConnection();
System.out.println(var1.equals(var2));
}
}
2.2,懒汉式
2.2.1,线程不安全
/**
* @Author zhou_ge
* @Date 2022/6/23 12:23
* @PackageName:xyz.zhouge.designPatterns.singleton.lazy.safety
* @ClassName: DataBase
* @Description: TODO
* @Version 1.0
*/
public class DataBase {
//1,将构造器私有化
private DataBase(){}
//2,声明私有化成员变量
private static DataBase connection = null;
//3,成员方法初始化成员变量
public static DataBase getConnection(){
//判空
if (connection == null){
connection = new DataBase();
}
return connection;
}
}
/**
* @Author zhou_ge
* @Date 2022/6/23 12:28
* @PackageName:xyz.zhouge.designPatterns.singleton.lazy.safety
* @ClassName: Client
* @Description: TODO
* @Version 1.0
*/
public class Client {
public static void main(String[] args) {
DataBase conn1 = DataBase.getConnection();
DataBase conn2 = DataBase.getConnection();
System.out.println(conn1.equals(conn2));
}
}
2.2.2,线程安全(同步锁)
/**
* @Author zhou_ge
* @Date 2022/6/23 12:30
* @PackageName:xyz.zhouge.designPatterns.singleton.lazy.unSafety
* @ClassName: DataBase
* @Description: TODO
* @Version 1.0
*/
public class DataBase {
private DataBase(){}
private static DataBase connection ;
public synchronized static DataBase getConnection(){
if (connection == null){
connection = new DataBase();
}
return connection;
}
}
/**
* @Author zhou_ge
* @Date 2022/6/23 12:32
* @PackageName:xyz.zhouge.designPatterns.singleton.lazy.safety
* @ClassName: Client
* @Description: TODO
* @Version 1.0
*/
public class Client {
public static void main(String[] args) {
DataBase conn1 = DataBase.getConnection();
DataBase conn2 = DataBase.getConnection();
System.out.println(conn1.equals(conn2));
}
}
2.3,双检锁(volatile模式)
/**
* @Author zhou_ge
* @Date 2022/6/23 14:42
* @PackageName:xyz.zhouge.designPatterns.singleton.lazy.doubleLock
* @ClassName: DataBase
* @Description: TODO
* @Version 1.0
*/
public class DataBase {
//private constructor
private DataBase(){}
//member variable ; volatile 保证关键字可以保证可见性和有序性
private static volatile DataBase connection ;
//public method
public static DataBase getConnection(){
//validate connection
if (connection == null){
//synchronized lock
synchronized (DataBase.class){
//validate again after getting the lock
if (connection == null){
connection = new DataBase();
}
}
}
return connection;
}
}
/**
* @Author zhou_ge
* @Date 2022/6/23 14:48
* @PackageName:xyz.zhouge.designPatterns.singleton.lazy.doubleLock
* @ClassName: Client
* @Description: TODO
* @Version 1.0
*/
public class Client {
public static void main(String[] args) {
DataBase conn1 = DataBase.getConnection();
DataBase conn2 = DataBase.getConnection();
System.out.println(conn1.equals(conn2));
}
}
2.4,静态内部类
/**
* @Author zhou_ge
* @Date 2022/6/23 14:53
* @PackageName:xyz.zhouge.designPatterns.singleton.lazy.static_inner_class
* @ClassName: DataBase
* @Description: TODO
* @Version 1.0
*/
public class DataBase {
//private constructor
private DataBase(){}
//static inner class
private static class DataBaseHolder{
private static final DataBase CONNECTION = new DataBase();
}
/**
* 静态内部类单例模式中实例由内部类创建,由于 JVM 在加载外部类的过程中, 是不会加载静态
* 内部类的, 只有内部类的属性/方法被调用时才会被加载, 并初始化其静态属性。静态属性由于被
* static 修饰,保证只被实例化一次,并且严格保证实例化顺序。
*
* 说明:
* 第一次加载Singleton类时不会去初始化INSTANCE,只有第一次调用getInstance,虚拟机加
* 载SingletonHolder
* 并初始化INSTANCE,这样不仅能确保线程安全,也能保证 Singleton 类的唯一性。
*
*/
//public method
public static DataBase getConnection(){
return DataBaseHolder.CONNECTION;
}
}
/**
* @Author zhou_ge
* @Date 2022/6/23 14:56
* @PackageName:xyz.zhouge.designPatterns.singleton.lazy.static_inner_class
* @ClassName: Client
* @Description: TODO
* @Version 1.0
*/
public class Client {
public static void main(String[] args) {
DataBase conn1 = DataBase.getConnection();
DataBase conn2 = DataBase.getConnection();
System.out.println(conn1.equals(conn2));
}
}
2.5,枚举方式
/**
* @Author zhou_ge
* @Date 2022/6/23 15:00
* @PackageName:xyz.zhouge.designPatterns.singleton.enum_
* @ClassName: DataBase
* @Description: 枚举方式实现
* @Version 1.0
*/
public enum DataBase {
Connection;
/**
*枚举类实现单例模式是极力推荐的单例实现模式,因为枚举类型是线程安全的,并且只会装载一
* 次,设计者充分的利用了枚举的这个特性来实现单例模式,枚举的写法非常简单,而且枚举类型是
* 所用单例实现中唯一一种不会被破坏的单例实现模式。
*/
}
/**
* @Author zhou_ge
* @Date 2022/6/23 15:00
* @PackageName:xyz.zhouge.designPatterns.singleton.enum_
* @ClassName: Client
* @Description: TODO
* @Version 1.0
*/
public class Client {
public static void main(String[] args) {
DataBase conn1 = DataBase.Connection;
DataBase conn2 = DataBase.Connection;
System.out.println(conn1.equals(conn2));
}
}
3,存在的问题
上面定义的单例类(Singleton)可以创建多个对象,枚举方式除外。有两种方式,分别是序列化和反射
3.1,序列化与反序列化
/**
* @Author zhou_ge
* @Date 2022/6/23 14:53
* @PackageName:xyz.zhouge.designPatterns.singleton.lazy.static_inner_class
* @ClassName: DataBase
* @Description: TODO
* @Version 1.0
*/
public class DataBase implements Serializable {
//private constructor
private DataBase(){}
//static inner class
private static class DataBaseHolder{
private static final DataBase CONNECTION = new DataBase();
}
/**
* 静态内部类单例模式中实例由内部类创建,由于 JVM 在加载外部类的过程中, 是不会加载静态
* 内部类的, 只有内部类的属性/方法被调用时才会被加载, 并初始化其静态属性。静态属性由于被
* static 修饰,保证只被实例化一次,并且严格保证实例化顺序。
*
* 说明:
* 第一次加载Singleton类时不会去初始化INSTANCE,只有第一次调用getInstance,虚拟机加
* 载SingletonHolder
* 并初始化INSTANCE,这样不仅能确保线程安全,也能保证 Singleton 类的唯一性。
*
*/
//public method
public static DataBase getConnection(){
return DataBaseHolder.CONNECTION;
}
//解决序列化破坏单例的方案
private Object readResolve(){
return DataBaseHolder.CONNECTION;
}
}
/**
* @Author zhou_ge
* @Date 2022/6/23 14:56
* @PackageName:xyz.zhouge.designPatterns.singleton.lazy.static_inner_class
* @ClassName: Client
* @Description: TODO
* @Version 1.0
*/
public class Client {
public static void main(String[] args) {
//writeObjectToFile();
DataBase conn1 = readObjectFromFile();
DataBase conn2 = readObjectFromFile();
System.out.println(conn1.equals(conn2));
}
//读取对象,写入文件
public static void writeObjectToFile(){
try {
//1,获取对象
DataBase conn = DataBase.getConnection();
//2,创建对象输出流
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("H:\\desktop\\a.txt"));
//3,将对象写入文件中
oos.writeObject(conn);
} catch (IOException e) {
e.printStackTrace();
}
}
//读取文件,转为对象
public static DataBase readObjectFromFile(){
DataBase conn = null;
try {
//1,获取文件
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("H:\\desktop\\a.txt"));
//2,读取对象
conn = (DataBase) ois.readObject();
System.out.println(conn);
} catch (Exception e) {
e.printStackTrace();
}finally {
return conn;
}
}
}
3.2,反射
/**
* @Author zhou_ge
* @Date 2022/6/23 14:42
* @PackageName:xyz.zhouge.designPatterns.singleton.lazy.doubleLock
* @ClassName: DataBase
* @Description: TODO
* @Version 1.0
*/
public class DataBase {
//private constructor
private DataBase(){
if (connection != null){
throw new RuntimeException();
}
}
//member variable ; volatile 保证关键字可以保证可见性和有序性
private static volatile DataBase connection ;
//public method
public static DataBase getConnection(){
//validate connection
if (connection != null){
return connection;
}
//synchronized lock
synchronized (DataBase.class){
//validate again after getting the lock
if (connection != null){
return connection;
}
connection = new DataBase();
return connection;
}
}
}
/**
* @Author zhou_ge
* @Date 2022/6/23 14:56
* @PackageName:xyz.zhouge.designPatterns.singleton.lazy.static_inner_class
* @ClassName: Client
* @Description: TODO
* @Version 1.0
*/
public class Client {
public static void main(String[] args) {
try {
//1,获取DataBase的字节码对象
Class<DataBase> clazz = DataBase.class;
//2,获取无参构造方法
Constructor<DataBase> constructor = clazz.getDeclaredConstructor();
//3,取消访问权限
constructor.setAccessible(true);
//4,获取对象
DataBase conn1 = constructor.newInstance();
DataBase conn2 = constructor.newInstance();
System.out.println(conn1.equals(conn2));
} catch (Exception e) {
e.printStackTrace();
}
}
}
4,Runtime源码解析
/**
* @Author zhou_ge
* @Date 2022/6/23 16:20
* @PackageName:xyz.zhouge.designPatterns.singleton.RuntimeDemo
* @ClassName: Test
* @Description: TODO
* @Version 1.0
*/
public class Test {
public static void main(String[] args) {
try {
//获取Runtime类对象
Runtime runtime = Runtime.getRuntime();
//返回 Java 虚拟机中的内存总量。
System.out.println(runtime.totalMemory());
//返回 Java 虚拟机试图使用的最大内存量。
System.out.println(runtime.maxMemory());
//创建一个新的进程执行指定的字符串命令,返回进程对象
Process process = runtime.exec("ipconfig");
//获取命令执行后的结果,通过输入流获取
InputStream inputStream = process.getInputStream();
byte[] arr = new byte[1024 * 1024 * 100];
int b = inputStream.read(arr);
System.out.println(new String(arr, 0, b, "gbk"));
} catch (Exception e) {
e.printStackTrace();
}
}
}
二、工厂模式
三、原型模式
用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型对象相同的新对象。
1,原型模式的结构
原型模式包含如下角色:
抽象原型类:规定了具体原型对象必须实现的的 clone() 方法。
具体原型类:实现抽象原型类的 clone() 方法,它是可被复制的对象。
访问类:使用具体原型类中的 clone() 方法来复制新的对象。
2,原型模式的分类
原型模式的克隆分为浅克隆和深克隆。
浅克隆:创建一个新对象,新对象的属性和原来对象完全相同,对于非基本类型属性,仍指向原有属性所指向的对象的内存地址。
深克隆:创建一个新对象,属性中引用的其他对象也会被克隆,不再指向原有对象地址。
3,浅克隆案例
3.1,案例一
3.1.1,克隆接口(抽象原型类)
/**
* @Author zhou_ge
* @Date 2022/6/28 12:44
* @PackageName:xyz.zhouge.designPatterns.prototype.shallowCloning.abstractObject
* @ClassName: Student
* @Description: TODO
* @Version 1.0
*/
public abstract class StudentPrototype implements Cloneable{
}
3.1.2,具体原型类
/**
* @Author zhou_ge
* @Date 2022/6/28 12:46
* @PackageName:xyz.zhouge.designPatterns.prototype.shallowCloning.specificObject
* @ClassName: Student
* @Description: TODO
* @Version 1.0
*/
public class Student extends StudentPrototype {
public Student() {
System.out.println("Student prototype object had created ...");
}
@Override
public Student clone() throws CloneNotSupportedException {
System.out.println("Student prototype object had cloned ...");
return (Student) super.clone();
}
}
3.1.3,访问类
/**
* @Author zhou_ge
* @Date 2022/6/29 14:24
* @PackageName:xyz.zhouge.designPatterns.prototype.shallow_clone
* @ClassName: Client
* @Description: TODO
* @Version 1.0
*/
public class Client {
public static void main(String[] args) throws CloneNotSupportedException {
Student stu1 = new Student();
Student stu2 = stu1.clone();
System.out.println(stu1 == stu2);//false ,shallow clone
/**
*
* 浅克隆:创建一个新对象,新对象的属性和原来对象完全相同,对于非基本类型属性,仍指向原有属性所指向的对象的内存地址。
*
* 深克隆:创建一个新对象,属性中引用的其他对象也会被克隆,不再指向原有对象地址。
*/
}
}
3.2,案例二
3.2.1,克隆接口(抽象原型类)
/**
* @Author zhou_ge
* @Date 2022/6/29 14:32
* @PackageName:xyz.zhouge.designPatterns.prototype.shallow_clone.demo2.abstractObject
* @ClassName: CitationPrototype
* @Description: TODO
* @Version 1.0
*/
public abstract class CitationPrototype implements Cloneable{
}
3.2.2,具体原型类
/**
* @Author zhou_ge
* @Date 2022/6/29 14:33
* @PackageName:xyz.zhouge.designPatterns.prototype.shallow_clone.demo2.specificObject
* @ClassName: Citation
* @Description: TODO
* @Version 1.0
*/
public class Citation extends CitationPrototype {
private String name ;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Citation() {
System.out.println("Citation object had created ...");
}
@Override
public Citation clone() throws CloneNotSupportedException {
System.out.println("Citation object had cloned ...");
return (Citation) super.clone();
}
public void showCitation(){
System.out.println(name + " 同学:在2021-2022学年第一学期中表现优秀,特发此状,以资鼓励!");
}
}
3.2.3,访问类
/**
* @Author zhou_ge
* @Date 2022/6/29 14:37
* @PackageName:xyz.zhouge.designPatterns.prototype.shallow_clone.demo2
* @ClassName: Client
* @Description: TODO
* @Version 1.0
*/
public class Client {
public static void main(String[] args) throws CloneNotSupportedException {
//test1();
test2();
}
public static void test1() throws CloneNotSupportedException {
//1,create prototype object
Citation c1 = new Citation();
c1.setName("zhangSan");
//2,clone prototype object
Citation c2 = c1.clone();
c2.setName("lisi");
c1.showCitation();
c2.showCitation();
System.out.println(c1 == c2);
/**
*
* 浅克隆:创建一个新对象,新对象的属性和原来对象完全相同,对于非基本类型属性,仍指向原有属性所指向的对象的内存地址。
*
* 深克隆:创建一个新对象,属性中引用的其他对象也会被克隆,不再指向原有对象地址。
*/
}
public static void test2() throws CloneNotSupportedException {
//1,create prototype object
Citation c1 = new Citation();
//2,clone prototype object
Citation c2 = c1.clone();
//3,set variable value
c1.setName("zhangSan");
c2.setName("lisi");
c1.showCitation();
c2.showCitation();
System.out.println(c1 == c2);
/**
*
* 浅克隆:创建一个新对象,新对象的属性和原来对象完全相同,对于非基本类型属性,仍指向原
* 有属性所指向的对象的内存地址。
*
* 深克隆:创建一个新对象,属性中引用的其他对象也会被克隆,不再指向原有对象地址。
*/
}
}
4,深克隆案例
4.1,案例一(浅克隆)
4.1.1,克隆接口(抽象原型类)
/**
* @Author zhou_ge
* @Date 2022/6/29 14:51
* @PackageName:xyz.zhouge.designPatterns.prototype.deep_clone.demo1.abstractObject
* @ClassName: CitationPrototype
* @Description: TODO
* @Version 1.0
*/
public abstract class CitationPrototype implements Cloneable{
}
4.1.2,具体原型类
/**
* @Author zhou_ge
* @Date 2022/6/29 14:53
* @PackageName:xyz.zhouge.designPatterns.prototype.deep_clone.demo1.specificObject
* @ClassName: Citation
* @Description: TODO
* @Version 1.0
*/
public class Citation extends CitationPrototype {
private Student stu ;
public Student getStu() {
return stu;
}
public void setStu(Student stu) {
this.stu = stu;
}
public void show(){
System.out.println(stu.getStuName() + " 同学:在2021-2022学年第一学期中表现优秀,特发此状,以资鼓励!");
}
@Override
public Citation clone() throws CloneNotSupportedException {
System.out.println("Citation object had cloned ...");
return (Citation) super.clone();
}
}
/**
* @Author zhou_ge
* @Date 2022/6/29 14:52
* @PackageName:xyz.zhouge.designPatterns.prototype.deep_clone.demo1.specificObject
* @ClassName: Student
* @Description: TODO
* @Version 1.0
*/
public class Student {
private String stuName ;
private String address ;
public Student(String stuName, String address) {
this.stuName = stuName;
this.address = address;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getStuName() {
return stuName;
}
public void setStuName(String stuName) {
this.stuName = stuName;
}
}
4.1.3,访问类
/**
* @Author zhou_ge
* @Date 2022/6/29 14:56
* @PackageName:xyz.zhouge.designPatterns.prototype.deep_clone.demo1
* @ClassName: Client
* @Description: TODO
* @Version 1.0
*/
public class Client {
public static void main(String[] args) throws CloneNotSupportedException {
//浅克隆:创建一个新对象,新对象的属性和原来对象完全相同,对于非基本类型属性(Student.stuName),仍指向原有属性所指向的对象的内存地址。
Student stu1 = new Student("zhangSan", "十堰");
Citation c1 = new Citation();
c1.setStu(stu1);
Citation c2 = c1.clone();
Student stu2 = c2.getStu();
stu2.setStuName("lisi");//c2对象是从c1克隆过来的,stu2是非基本类型,修改stu2的属性值,也会把stu1的进行修改
System.out.println(stu1 == stu2);
c1.show();
c2.show();
/**stu对象和stu1对象是同一个对象,就会产生将stu1对象中name属性值改为“李四”,两个
Citation(奖状)对象中显示的都是李四。这就是浅克隆的效果,对具体原型类(Citation)中的
引用类型的属性进行引用的复制。这种情况需要使用深克隆,而进行深克隆需要使用对象流
*/
}
}
4.2,案例二
4.2.1,原型接口(抽象原型类)
/**
* @Author zhou_ge
* @Date 2022/6/29 14:51
* @PackageName:xyz.zhouge.designPatterns.prototype.deep_clone.demo1.abstractObject
* @ClassName: CitationPrototype
* @Description: TODO
* @Version 1.0
*/
public abstract class CitationPrototype implements Cloneable{
}
4.2.2,具体原型类
/**
* @Author zhou_ge
* @Date 2022/6/29 14:53
* @PackageName:xyz.zhouge.designPatterns.prototype.deep_clone.demo1.specificObject
* @ClassName: Citation
* @Description: TODO
* @Version 1.0
*/
public class Citation extends CitationPrototype implements Serializable {
private Student stu ;
public Student getStu() {
return stu;
}
public void setStu(Student stu) {
this.stu = stu;
}
public void show(){
System.out.println(stu.getStuName() + " 同学:在2021-2022学年第一学期中表现优秀,特发此状,以资鼓励!");
}
@Override
public Citation clone() throws CloneNotSupportedException {
System.out.println("Citation object had cloned ...");
return (Citation) super.clone();
}
}
/**
* @Author zhou_ge
* @Date 2022/6/29 14:52
* @PackageName:xyz.zhouge.designPatterns.prototype.deep_clone.demo2.specificObject
* @ClassName: Student
* @Description: TODO
* @Version 1.0
*/
public class Student implements Serializable {
private String stuName ;
private String address ;
public Student(String stuName, String address) {
this.stuName = stuName;
this.address = address;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getStuName() {
return stuName;
}
public void setStuName(String stuName) {
this.stuName = stuName;
}
}
4.2.3,访问类
/**
* @Author zhou_ge
* @Date 2022/6/29 15:06
* @PackageName:xyz.zhouge.designPatterns.prototype.deep_clone.demo2
* @ClassName: Client
* @Description: TODO
* @Version 1.0
*/
public class Client {
public static void main(String[] args) throws Exception {
shallow_clone();
System.out.println("======================");
deep_clone();
}
public static void shallow_clone() throws Exception {
//浅克隆:创建一个新对象,新对象的属性和原来对象完全相同,对于非基本类型属性(Student.stuName),仍指向原有属性所指向的对象的内存地址。
Student stu1 = new Student("zhangSana", "十堰");
Citation c1 = new Citation();
c1.setStu(stu1);
Citation c2 = c1.clone();
Student stu2 = c2.getStu();
stu2.setStuName("lisi");//c2对象是从c1克隆过来的,stu2是非基本类型,修改stu2的属性值,也会把stu1的进行修改
System.out.println(stu1 == stu2);
c1.show();
c2.show();
/**stu对象和stu1对象是同一个对象,就会产生将stu1对象中name属性值改为“李四”,两个
Citation(奖状)对象中显示的都是李四。这就是浅克隆的效果,对具体原型类(Citation)中的
引用类型的属性进行引用的复制。这种情况需要使用深克隆,而进行深克隆需要使用对象流
*/
}
public static void deep_clone() throws Exception {
//1,创建citaion对象
Student stu1 = new Student("zhangSan", "shiyan");
Citation c1 = new Citation();
c1.setStu(stu1);
//2,写入对象
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("H:\\desktop\\temp.txt"));
oos.writeObject(c1);
oos.close();
//3,读取对象
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("H:\\desktop\\temp.txt"));
Citation c2 = (Citation) ois.readObject();
Student stu2 = c2.getStu();
stu2.setStuName("lisi");
c1.show();
c2.show();
System.out.println(stu1 == stu2);
}
}
四、建造者模式
将一个复杂对象的构建与表示分离,使得同样的构建过程可以创建不同的表示。
-分离了部件的构造(由Builder来负责)和装配(由Director负责)。 从而可以构造出复杂的对象。这个模式适用于:某个对象的构建过程复杂的情况。
-由于实现了构建和装配的解耦。不同的构建器,相同的装配,也可以做出不同的对象;相同的构建器,不同的装配顺序也可以做出不同的对象。也就是实现了构建算法、装配算法的解耦,实现了更好的复用。
-建造者模式可以将部件和其组装过程分开,一步一步创建一个复杂的对象。用户只需要指定复杂对象的类型就可以得到该对象,而无须知道其内部的具体构造细节。
1,建造者模式的结构
建造者(Builder)模式包含如下角色:
抽象建造者类(Builder):这个接口规定要实现复杂对象的那些部分的创建,并不涉及具体的部件对象的创建。
具体建造者类(ConcreteBuilder):实现 Builder 接口,完成复杂产品的各个部件的具体创建方法。在构造过程完成后,提供产品的实例。
产品类(Product):要创建的复杂对象。
指挥者类(Director):调用具体建造者来创建复杂对象的各个部分,在指导者中不涉及具体产品的信息,只负责保证对象各部分完整创建或按某种顺序创建。
2,建造者模式案例
【创建共享单车】
生产自行车是一个复杂的过程,它包含了车架,车座等组件的生产。而车架又有碳纤维,铝合金等材质的,车座有橡胶,真皮等材质。对于自行车的生产就可以使用建造者模式。
这里Bike是产品,包含车架,车座等组件;Builder是抽象建造,MobikeBuilder和OfoBuilder是具体的建造者;Director是指挥者。