创建型模式 主要是用于产生类实例,也就是new 对象
共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
一.单例模式
1.一句话描述
- 确保一个类只会生成一个实例,并提供一个全局访问点
2.实现方式
单例模式可以细分懒汉模式和饿汉模式两种模式:
(1).懒汉模式
public class Singleton{
//使用volatile关键字防止重排序,因为 new 实例是一个非原子操作
private volatile static Singleton singleton;
//私有构造函数
private Singleton(){}
public static Singleton getSingleton(){
if(singleton==null){
//只对实例化代码块加锁,提升性能
synchronized (Singleton.class){
if (singleton == null) { //双重检查
singleton = new Singleton();
}
}
}
return singleton;
}
}
在JDK1.4及更早版本的JAVA中,volatile关键字的实现会导致双重检查加锁的失效
(2).饿汉模式
public class Singleton{
private static Singleton singleton = new Singleton();
//私有构造函数
private Singleton(){}
public static Singleton getSingleton(){
return singleton;
}
}
利用JVM在加载完这个类时,马上实例化唯一的实例,保证线程安全
实战场景:
- Spring Bean 管理默认就是一种单例模式
二、工厂模式
1.一句话描述
- 定义一个创建对象的接口,由子类实例化具体对象,一个具体子类对应一种产品类对象
2. 实现方式
(1) 简单工厂
class Juice{ }
class AppleJuice extends Juice{}
class PearJuice extends Juice{}
class JuiceStore{
public static Juice createJuice(String fruit) { //简单工厂方法, 新增产品类,需要修改工厂方法,不符合开闭原则
if ("apple".equals(fruit)) {
return new AppleJuice();
} else if ("pear".equals(fruit)) {
return new PearJuice();
} else {
return null;
}
}
}
(2)工厂 方法
class Juice{ } //抽象产品类
class AppleJuice extends Juice{} //具体产品类
class PearJuice extends Juice{}
abstract class JuiceStore{ //抽象工厂类
public abstract Juice createJuice();
}
class AppleStore extends JuiceStore { //具体产品类
@Override
public Juice createJuice() {
return new AppleJuice();
}
}
class PearStore extends JuiceStore{//具体产品类
@Override
public Juice createJuice() {
return new PearJuice();
}
}
3. 类图
image.png4.总结
1.工厂模式相比简单工厂,加入了"开闭原则", 创建工厂和 产品实现解耦
2.每增加一个产品实现类,要增加一个工厂创建类
3.工厂模式 是抽象工厂的一个比较常见的情况
三、抽象工厂模式
1.一句话描述
- 提供一个负责创建一组产品的接口,接口内每个方法由子类负责创建一个具体产品
2.类图/实例
class Juice{}
class AppleJuice extends Juice{}
class IceAppleJuice extends AppleJuice { }
class CommonAppleJuice extends AppleJuice{}
class PearJuice extends Juice{}
class IcePearJuice extends PearJuice { }
class CommonPearJuice extends PearJuice{}
//超级工厂,包含两个工厂方法
abstract class Store{
public abstract Juice createAppleJuice();
public abstract Juice createPearJuice();
}
class OneStore extends Store {
@Override
public Juice createAppleJuice() {
return new IceAppleJuice();
}
@Override
public Juice createPearJuice() {
return new IcePearJuice();
}
}
class TwoStore extends Store{
@Override
public Juice createAppleJuice() {
return new CommonAppleJuice();
}
@Override
public Juice createPearJuice() {
return new CommonPearJuice();
}
}
3.实战案例
4.总结
1.在一个工厂里聚合多个同类产品(同类产品的不同系列)
2.简化产品族的交换
3.产品族要扩展,需要修改所有工厂类,不易扩展产品族
四、原型模式
1. 一句话描述
- 利用原对象快速复制一个对象
2.实战案例
- Object 对象clone方法,本地方法默认实现浅克隆
- Spring中原型bean的创建,就是原型模式的应用
3.实现方式
分为浅克隆和深克隆
- 浅克隆:创建一个新对象,新对象的属性和原来对象完全相同,对于非基本类型属性,仍指向原
有属性所指向的对象的内存地址, 也就是引用类型指向的是同一个
// 实现Cloneable接口
public class InstanceClone implements Cloneable{
// ...省略
@Override
protected Object clone() {
Object clone = null;
try {
clone = super.clone();
} catch (CloneNotSupportedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// TODO Auto-generated method stub
return clone;
}
}
- 深克隆:创建一个新对象,属性中引用的其他对象也会被克隆,不再指向原有对象地址。
//通过对象的序列化实现
public Object deepClone() {
//创建流
ByteArrayOutputStream bos = null;
ObjectOutputStream oos = null;
ByteArrayInputStream bis =null;
ObjectInputStream ois = null;
try {
//序列化
bos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(bos);
oos.writeObject(this);//当前的对象以流的方式输出
//反序列化
bis = new ByteArrayInputStream(bos.toByteArray());
ois = new ObjectInputStream(bis);
InstanceClone deepClone = (InstanceClone )ois.readObject();
return deepClone ;
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
return null;
}finally {
try {
bos.close();
oos.close();
bis.close();
ois.close();
} catch (Exception e2) {
// TODO: handle exception
}
}
}
也可以通过重写clone方法来实现深拷贝,但不推荐
4.总结
1.原型模式可以快速创建复杂对象,同时提高效率
2.需要在类中实现克隆方法, 违背了OCP开闭原则
五、建造者模式
1. 一句话描述
- 对复杂对象的组件创建以及组合进行了抽取和拆分
2.类图
image.png3. 实战场景
- JDK中 StringBuilder
- MybatisPlus中的QueryWrapper对象的构建
- Mybatis中用到的建造者模式:SqlSessionFactoryBuilder、XMLConfigBuilder、XMLMapperBuilder、XMLStatementBuilder、CacheBuilder等
4.总结
1.将复杂对象的创建步骤分解在不同的方法中,使得创建过程更加清晰,对象创建更加灵活
2.使用方不必知道对象内部组成细节,对象本身和对象创建过程解耦
3.如果对象内部发生变化, 建造者都要修改,成本较大,适用于对象组成部分基本相同
网友评论