概述
设计模式总结,创建型模式篇.
创建型模式
创建型模式,主要作用是创建对象.最简单的方式就是new一个对象.通过构造器或者set方法注入属性.也可以通过设计模式提供更好的创建对象的方式.
简单工厂模式
只生产同一类型的工厂模式
1 | public class PhoneFactory { |
简单工厂模式.一个工厂模式(xxxFactory),通过静态方法传入特定的参数,根据不同的参数,多个子类(或实现同一接口)的不同的对象(huawei&apple)并返回给调用者.强调一个工厂类只生产同一个类型,PhoneFactory就只是负责生产各个类型的phone.
工厂模式
当需要两个以上的工厂时.
1 | public interface PhoneFactory { |
其中Mate20,Mate30,Iphone11,IphoneXR都继承自Phone.
调用代码
1 | public class APP { |
虽然factory.makePhone(“2019”);都是传入同样的参数(“2019”),但是创建的对象却是不一样的.
创建工厂对象的类型,决定了生产什么品牌的phone.
抽象工厂模式
涉及到统一类型(品牌)的对象,需要引入抽象工厂模式了.
前面的工厂模式,生产的对象会出现一个问题.
1 | //生产华为的数据线type-c |
apple家生产的手机和华为家生产的数据线并不能通用.容易出错.
此时需要抽象工厂模式.
1 | public interface PhoneFactory { |
调用方式
1 | public static void main(String[] args) { |
此时不再需要单独选择Factory生产手机和数据线了.只需要选择该品牌下的Factory,会针对性的生产互相兼容的产品.
单例模式
饿汉式
1 | public class Singleton { |
优点:
- 线程安全.
- 在类加载的同时,已经创建好一个静态对象,调用时无需再次创建.
缺点:
- 资源效率不高.无论是否需要用到getInstance()方法,但是在执行该类的其他静态方法或者加载了该类(class.forName)时,依然会创建对象.
懒汉式
1 | public class Singleton { |
双重检查,两次instance是否为null.
使用volatile修饰的变量,会保证线程可见性(当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看得到修改的值),但是并不会保证原子性(即一个操作或者多个操作,要么全部执行并且执行的过程不会被任何因素打断,要么就都不执行)
使用volatile关键字修饰共享变量还可以禁止重排序(编译器和处理器为了优化程序性能而对指令序列进行排序的一种手段).
比如a=1;b=2;c=a+b.变量a和b可能会发生重排序(b=2先执行),因为a和b的执行顺序并不会影响到最终c的结果(c不会重排序).这是在单线程的前提下.
如果是多线程
1 | public class TestVolatile { |
a = 2;和status = true;可能会发生重排序.status = true;先被执行,从而影响最终的结果.
嵌套类
1 | public class Singleton3 { |
枚举类
用枚举实现单例,它在类加载的时候会初始化里面的所有的实例,而且 JVM 保证了它们不会再被实例化,所以它天生就是单例的.
建造者模式
先 new 一个 Builder,然后可以链式地调用一堆方法,最后再调用一次 build() 方法,创建需要的对象.
1 | class User { |
当属性很多,而且有些必填,有些选填的时候.建造者模式会使代码清晰很多.
在 build() 方法中校验各个参数比在 User 的构造方法中校验,可以让代码优雅一些.
lombok 插件,使用@Builder注解
1 |
|
提供了建造者模式的注解.
原型模式
一个原型实例,基于这个原型实例产生新的实例,也就是clone.
Object 类中有一个 clone() 方法,它用于生成一个新的对象.Java要求该类必须先实现 Cloneable 接口.如果没有实现该接口,在 clone() 的时候,就会抛出 CloneNotSupportedException 异常.
java 的克隆是浅克隆,碰到对象引用的时候,克隆出来的对象和原对象中的引用都会指向同一个内存地址.
通常实现深克隆的方法是将对象进行序列化,然后再进行反序列化.
总结
简单工厂模式,通过一个工厂,创建同一类型的对象.
工厂模式,需要创建对应的工厂,如果根据该工厂对象创建对应的对象.
抽象工厂模式,抽象出来一个类型,在该类型上不必关心兼容,解决存在兼容性问题.
单例模式,创建单个对象,为安全的同时,节省资源.
建造者模式,当一个类属性很多,有些必填,有些选填的时候,可以使用建造者模式.让代码更加优雅.
原型模式,了解 Object 类中的 clone() 方法相关的知识即可,用的比较少.