「这是我参与11月更文挑战的第27天,活动详情查看:2021最后一次更文挑战」
创建型模式,主要是用于组件对象的创建,
主要有五种:
- 单例模式,(在系统中有且只有一个对象)
- 工厂方法模式
- 抽象工厂模式
- 建造者模式(工人可能关注与创建对象的细节过程)
- 原型模式(克隆一个爱因斯坦)
2.单例模式:(Singleton)
单例的有且只有一个实例对象
要点:
创建-构造器私有
可以外部访问
静态;
**
**
我自己写的是这样的:
package com.atlucas.creation.singleton;
/**
* @author lucas
* @create 2021-03-18 15:01
* @description 单例模式的实体类
*/
public class Person {
private String name;
private Integer age;
/**
* 单例模式;要求此系统中有且只有一个实例对象;
*
* 1.确定是饿汉式还是懒汉式,然后创建一个静态的私有变量
* 2.构造器私有化
* 3.外部访问对象,要从我们自己构造好的私有对象返回 *
*/
/**
* 1.确定是饿汉式还是懒汉式,然后创建一个静态的私有变量
* private static final Person Instanc=new Peson(); 饿汉式,不让变动
*/
private static Person Instance; //懒汉式时间换空间
/**
* 2.构造器私有化
*/
private Person (){
System.out.println("需要创建一个对象person");
}
/**3.外部访问
* 公共的静态方法-->利用静态存储方法区,
* 建立一个静态的空对象,如果需要就一直存在,直至程序完结
* @return
*/
public static Person getPerson(){
//多线程情况下不安全
if (Instance==null){
Person person=new Person();
Instance=person;
}
return Instance;
}
public static void main(String[] args) {
//静态的公共获取方法--对象都一样
Person person1 = Person.getPerson();
Person person2 = Person.getPerson();
System.out.println(person1==person2);
}
}
\
上述的情况在于多线程的是不安全的;
\
\
优化一:
\
/**3.外部访问
* 公共的静态方法-->利用静态存储方法区,
* 建立一个静态的空对象,如果需要就一直存在,直至程序完结
* @return
*/
public static synchronized Person getPerson(){
//多线程情况下不安全
if (Instance==null){
Person person=new Person();
Instance=person;
}
return Instance;
}
\
\
优化二:
\
2.1标准的单例模式:
package com.atlucas.creation.singleton;
/**
* @author lucas
* @create 2021-03-18 15:01
* @description 单例模式的实体类
*/
public class Person {
private String name;
private Integer age;
/**
* 单例模式;要求此系统中有且只有一个实例对象;
*
* 1.确定是饿汉式还是懒汉式,然后创建一个静态的私有变量
* 2.构造器私有化
* 3.外部访问对象,要从我们自己构造好的私有对象返回 *
*/
/**
* 1.确定是饿汉式还是懒汉式,然后创建一个静态的私有变量
* private static final Person Instanc=new Peson(); 饿汉式,不让变动
*/
private static volatile Person Instance;
/**
* 2.构造器私有化
*/
private Person (){
System.out.println("需要创建一个对象person");
}
/**3.外部访问
* 公共的静态方法-->利用静态存储方法区,
* 建立一个静态的空对象,如果需要就一直存在,直至程序完结
* @return
*/
public static Person getPerson(){
//多线程情况下不安全
if (Instance==null){
synchronized (Person.class){
//同步代码块+双重检查锁(+ volatile内存可见性,创建对象防止指令重排序)
if (Instance==null){
Person person=new Person();
Instance=person;
}}
}
return Instance;
}
public static void main(String[] args) {
//静态的公共获取方法--对象都一样
Person person1 = Person.getPerson();
Person person2 = Person.getPerson();
System.out.println(person1==person2);
}
}
\
对于单列模式:基本是双重锁+内存可见性
**
**
**
**
**
**
2.2.单例模式的适用场景:
系统信息,环境变量的基础信息:
**
**
**
**
**
**
3.原型模式:(Prototype)
创建很多重复的对象,不影响性能;
\
比如我们查询相同的数据, 如果mybatis查询数据库,很多相同的记录,是多个相同的user
\
\
原型模式,主要是利于缓存,-->每次返回一个不一样的克隆体供我们使用
\
本体给外部返回一个克隆体
**
**
**
**
深拷贝和浅拷贝
**
**
package com.atlucas.creation.prototype;
import javax.jws.soap.SOAPBinding;
import java.util.HashMap;
/**
* @author lucas
* @create 2021-03-18 16:38
* @description 测试原型模型,创建相同的属性对象,但不会影响性能
*/
public class TestProtoType {
public static HashMap <String,User> prototypeCache=new HashMap<String, User>();
public User getUser() throws CloneNotSupportedException {
//缓存,相同的数据再缓存中拿取出来
/**
* 比如我们查询一个名称,给我们返回一个数据记录
*/
TestProtoType type = new TestProtoType();
//缓存中不存在
if (!prototypeCache.containsKey("lucas")) {
//从数据库取出来
User user = TestProtoType.getUserfromDB();
return user;
} else {
User user = prototypeCache.get("1");
//拿到原型之后--->实现克隆体
User clone = (User) user.clone();
return clone;
}
}
//获取数据库的数据对象
private static User getUserfromDB() throws CloneNotSupportedException {
System.out.println("获取数据库中的对象");
User user=new User();
user.setUserName("lucas");
user.setAge(23);
user.setUserID("10086123");
//放入缓存,原型-->克隆体,所以每次获取都会创建一个克隆体
User put = prototypeCache.put("1", (User) user.clone());
return user;
}
public static void main(String[] args) throws CloneNotSupportedException {
TestProtoType t1=new TestProtoType();
User user = t1.getUser();
TestProtoType t2=new TestProtoType();
User user1 = t2.getUser();
System.out.println(user==user1);
}
}
\
\
package com.atlucas.creation.prototype;
import netscape.security.UserDialogHelper;
import javax.jws.soap.SOAPBinding;
/**
* @author lucas
* @create 2021-03-18 16:39
* @description 对于使用一个原型模式的
* 比如基本创建多个相同的对象,但是不会影响性能
*/
public class User {
private String userName;
private Integer age;
private String UserID;
public User(){
System.out.println("创建一个user对象");
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getUserID() {
return UserID;
}
public void setUserID(String userID) {
UserID = userID;
}
@Override
public String toString() {
return "User{" +
"userName='" + userName + ''' +
", age=" + age +
", UserID='" + UserID + ''' +
'}';
}
/**
* 重写克隆方法
*/
@Override
protected Object clone() throws CloneNotSupportedException {
User user=new User();
//放入对象属性,浅拷贝-对象的内存指向没有变化
user.setAge(this.age);
user.setUserID(this.UserID);
user.setUserName(this.userName);
return user.clone();
}
}