原文链接:公众号狂神说
视频教程[狂神说B站]: https://www.bilibili.com/video/BV1K54y197iS
如有侵权,联系立删
省去new的过程
单例模式、工厂模式、抽象工厂模式、建造者模式、原型模式
一上来就能把所有东西都加载
(1)一上来就加载对象;
(2)可能造成内从空间的浪费
public class Hungry {
private Hungry() {
System.out.println("我是一个饿汉");
}
//一上来就加载单例对象,但是这个对象可能目前不会用到,浪费内存空间
private final static Hungry HUNGRY = new Hungry();
public static Hungry getInstance() {
return HUNGRY;
}
public static void main(String[] args) {
HUNGRY.getInstance();
}
}
用到时才创建单例对象
public class LazyMan {
private LazyMan() {
System.out.println("ok");
}
private static LazyMan lazyMan;
public static LazyMan getInstance() {
//判断单例对象是否存在,不存在则创建对象
if(lazyMan == null) {
lazyMan = new LazyMan();
}
return lazyMan;
}
public static void main(String arg[]) {
lazyMan.getInstance();
}
}
缺点:只适合单线程模式,不适用多线程并发情况
public static void main(String arg[]) {
for(int i = 0;i<10 ;i++) {
new Thread(()->{
LazyMan.getInstance();
}).start();
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XP04Vod5-1590330809555)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\1589022933004.png)]
解决方案:加锁
//解决多线程并发问题
if(lazyMan == null) {
//如果lazyMan对象不存在,给LazyMan.class加锁
//给类加锁,则该类只能用一个对象
synchronized (LazyMan.class) {
if(lazyMan == null)
{
lazyMan = new LazyMan();
}
}
}
存在问题:指令重排:
if(lazyMan == null) {
//如果lazyMan对象不存在,给LazyMan.class加锁
//给类加锁,则该类只能用一个对象
synchronized (LazyMan.class) {
if(lazyMan == null)
{
//new不是一个原子性操作
lazyMan = new LazyMan();
/*
* 1、分配内存空间
* 2、执行构造方法,初始化对象
* 3、把这个对象指向这个空间
*
* 这三步顺序可能被重排
* A 1 3 2
* B 1 //此时空间被A线程对象占用,但此时lazyMan还未完成构造
* B判断lazyMan !=null,返回lazyMan对象;
* 但此时空间内还没有对象,会造成问题
*/
}
}
}
解决办法:volatile
private volatile static LazyMan lazyMan;
public class Holder {
private Holder() {}
public static Holder getInstance() {
return InnerClass.HOLDER;
}
public static class InnerClass {
private static final Holder HOLDER = new Holder();
}
}
因为存在反射,所以以上几种方法都存在问题,使用枚举可以解决
1、作用:实现创建者和调用者分离
2、00P七大原则:
(1)开闭原则: 一个软件的实体应当对扩展开放,对修改关闭;
(2)依赖倒转原则:要针对接口编程,不要针对实现编程;
(3)迪米特法则:只与你直接的朋友通信,而避免和陌生人通信;
3、核心本质:
(1)实例化对象不使用new, 用工厂方法代替
(2)将选择实现类, 创建对象统一管理和控制。 从而将调用者跟我们的实现类解耦。
5 三种模式:
(1)简单工厂模式
用来生产同一等级结构中的任意产品(对于增加新的产品,需要修改已有代码)
(2)工厂方法模式
用来生产同一等级结构中的固定产品(支持增加任意产品)
(3)抽象工厂模式
围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。
1、缺点:新增类(产品)时需要在工厂类中修改代码,不符合开闭原则
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-h86vo1ie-1590330809561)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\1589024873595.png)]
Car.java(Car接口)
public interface Car {
void name();
}
wuling.java(五菱类)
public class wuling implements Car{
@Override
public void name() {
System.out.println("五菱");
}
}
Tesla.java(特斯拉类)
public class Tesla implements Car{
@Override
public void name() {
System.out.println("特斯拉");
}
}
Carfactory.java(车工厂类)
public class CarFactory {
//方法一
public static Car getCar(String car) {
//如果添加其他类,需要修改下列代码,修改逻辑
if (car.equals("五菱")) {
return new wuling();
}else if (car.equals("特斯拉")) {
return new Tesla();
}else {
return null;
}
}
//方法二
public static Car getwuling() {
return new wuling();
}
public static Car getTesla() {
return new Tesla();
}
}
CarFactorytest1.java(测试类)
import simplefactory.Car;
import simplefactory.CarFactory;
public interface CarFactirytest1 {
public static void main(String args[]) {
Car car1 = CarFactory.getCar("五菱");
Car car2 = CarFactory.getCar("特斯拉");
car1.name();
car2.name();
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kgWjgMOz-1590330809567)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\1589027170664.png)]
actirytest1 {
public static void main(String args[]) {
Car car1 = CarFactory.getCar("五菱");
Car car2 = CarFactory.getCar("特斯拉");
car1.name();
car2.name();
}
}
[外链图片转存中…(img-kgWjgMOz-1590330809567)]