前言
由于博主是边学边更新,所以难免会有瑕疵甚至错误,发现可私信于我,第一时间内修改
预计更新完之后总体上会再次整理一遍
ps:本文更倾向于初学过设计模式,而又没完全记住,相当于用来复习的笔记
创建型模式
单例模式
饿汉式
饿汉式:类加载的时候就创建出实例
/*
弊端:
即使此单例不需要使用,它也会在类加载后创建出来。占用内存,并增加类的初始化时间
*/
public class Hungry {
// 类的初始化的时候就创建对象
private static Hungry instance = new Hungry();
// 无参构造设为private,防止其他类通过构造方法实例化
private Hungry(){
}
// 通过该静态方法才可获取实例
public static Hungry getInstance(){
return instance;
}
}
懒汉式
懒汉式:先声明一个空变量,需要使用的时候才创建实例
双检锁方式实现懒汉式单例
public class Lazy {
// 防止重排序使用volatile关键字
// 重排序会在特殊情况下导致线程不安全
private static volatile Lazy instance = null;
// 保证其他类无法通过构造方法创建实例
private Lazy(){
}
public static Lazy getInstance(){
// 不加这个判空,则每次都要加锁,影响性能
if(instance == null){
// 加锁保证线程安全
synchronized (Lazy.class){
// 这里不加判空同样可能存在多次创建实例的情况
if (instance == null){
instance = new Lazy();
}
}
}
return instance;
}
}
静态内部类实现懒汉式单例
内部类是在使用时才会加载,所以可以实现懒加载
虚拟机底层是保证了类加载的时候是线程安全的,所以在懒加载创建实例的时候一定是线程安全的
public class StaticLazy {
// 静态内部类
private static class StaticLazyHolder {
public static StaticLazy instance = new StaticLazy();
}
// 私有化构造方法
private StaticLazy(){
}
public static StaticLazy getInstance(){
return StaticLazyHolder.instance;
}
}
总结
对于构建不复杂,加载完成后会立即使用的单例对象,推荐使用饿汉式
对于构建过程耗时较长,并不是所有使用此类都会用到的单例对象,推荐使用懒汉式
工厂模式
最终版抽象工厂模式
总接口,所有的工厂类都必须实现此接口
// Factory接口
public interface Factory {
// 提供创建实例的方法
Fruit create();
}
具体工厂类可以封装(创建类实例时的)细节
// 苹果工厂类
public class AppleFactory implements Factory{
// 封装创建时的具体细节
@Override
public Fruit create() {
return new Apple();
}
}
用户调用
/*
这是最终版本的抽象工厂模式
优点:
想要修改创建的具体工厂类,只需要改一行代码即可实现,修改之后调用的方法随之改变成对应的工厂实现
缺点:
如果Factory接口需要新增功能,会影响到所有具体的工厂类
所以只适合增加同类具体工厂,而不适合新增功能
*/
// 创建苹果
Factory appleFactory = new AppleFactory();
// 直接调用接口提供的方法,不用知道具体细节
Fruit apple = appleFactory.create();
// 创建梨子
Factory pearFactory = new PearFactory();
// 直接调用接口提供的方法,不用知道具体细节
Fruit peat = pearFactory.create();
建造型模式
建造型模式用于创建过程稳定,但配置多变的对象
将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示
好处在于不会忘记指定配置,保证构建的过程是稳定的
public class MilkTea {
// 口味类型
private String type;
// 大杯 中杯
private String size;
// 是否加珍珠
private boolean pearl;
// 是否加冰
private boolean ice;
public String getType() {
return type;
}
public String getSize() {
return size;
}
public boolean isPearl() {
return pearl;
}
public boolean isIce() {
return ice;
}
private MilkTea(MilkTeaBuilder builder) {
this.type = builder.type;
this.size = builder.size;
this.pearl = builder.pearl;
this.ice = builder.ice;
}
@Override
public String toString() {
return "MilkTea{" +
"type='" + type + '\'' +
", size='" + size + '\'' +
", pearl=" + pearl +
", ice=" + ice +
'}';
}
// 建造者
public static class MilkTeaBuilder{
private String type;
private String size;
private boolean pearl;
private boolean ice;
public MilkTeaBuilder(String type) {
this.type = type;
}
public MilkTeaBuilder size(String size){
this.size = size;
return this;
}
public MilkTeaBuilder pearl(boolean pearl){
this.pearl = pearl;
return this;
}
public MilkTeaBuilder ice(boolean ice){
this.ice = ice;
return this;
}
public MilkTea Builder(){
return new MilkTea(this);
}
}
}
用户建造一杯奶茶
MilkTea milkTea = new MilkTea.MilkTeaBuilder("蓝莓味")
.size("大杯")
.pearl(true)
.ice(false)
.Builder();
System.out.println(milkTea);
原型模式
其实就是给对象提供一个clone方法克隆出新对象
public class MilkTea {
// 口味类型
private String type;
// 是否加冰
private boolean ice;
/*
克隆当前实例
ps: 如下重写clone方法是无法克隆非基本类型的(会直接引用当前的)(浅拷贝),需要自行修改
*/
@Override
public MilkTea clone() throws CloneNotSupportedException {
return (MilkTea) super.clone();
}
}