简单的几种java设计模式(共23种)

重要的几种设计模式

1.1 单例模式

最重要的思想是构造器私有,保证其他人无法new这个对象

1.12 饿汉式

/*
 * 单例模式学习-饿汉式
 */
public class SingleObj {
//  通过饿汉式创建对象,会将此类中所有方法和属性提前创建出来,会占用一定的空间,如果不使用这个对象,就会造成资源上的浪费
    private String[] str = new String[1024];
    private String[] str1 = new String[1024];
    private String[] str2 = new String[1024];
//    ...属性
    /*public void show();
    * ...方法
    * */
    private SingleObj(){}//构造器私有

    private final static SingleObj singleObj = new SingleObj();//饿汉式,无论是否使用这个对象,先创建出来

    public static SingleObj getInstance(){
        return singleObj;
    }
}

1.13 DCL懒汉式

1.131 普通懒汉式
package com.hr.singleInstance;

/*
 * 单例模式学习-普通懒汉式
 */
public class SingleObj {
//  通过懒汉式创建对象,只会在需要的时候才会创建此类中所有方法和属性,相比饿汉式要节省资源
    private String[] str = new String[1024];
    private String[] str1 = new String[1024];
    private String[] str2 = new String[1024];
//    ...属性
    /*public void show();
    * ...方法
    * */
    private SingleObj(){}//构造器私有

    private static SingleObj singleObj;//懒汉式,默认为null

//    缺点:在普通情况下可以符合“单例”的需求,但是在多线程下,就会创建多个对象
    public static SingleObj getInstance(){
        if(singleObj==null){
            singleObj = new SingleObj();
        }
        return singleObj;
    }
}

//启动5个线程,进行启动,并都去获得懒汉式的单例对象,会发现有不同的对象
class Test{
    public static void main(String[] args) {
        for (int i = 0; i < 5; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    SingleObj obj = SingleObj.getInstance();
                    System.out.println(obj);
                }
            }).start();
        }
    }
}
控制台显示结果:
com.hr.singleInstance.SingleObj@5ab10c2d
com.hr.singleInstance.SingleObj@20c6ebb
com.hr.singleInstance.SingleObj@20c6ebb
com.hr.singleInstance.SingleObj@2aafbcf4
com.hr.singleInstance.SingleObj@5ab10c2d
1.132 双重检测锁的懒汉模式
package com.hr.singleInstance;

/*
 * 单例模式学习-DCL懒汉式(双重检测锁下的懒汉式)
 */
public class SingleObj {
//  通过懒汉式创建对象,只会在需要的时候才会创建此类中所有方法和属性,相比饿汉式要节省资源
    private String[] str = new String[1024];
    private String[] str1 = new String[1024];
    private String[] str2 = new String[1024];
//    ...属性
    /*public void show();
    * ...方法
    * */
    private SingleObj(){}//构造器私有

    private static SingleObj singleObj;//懒汉式,默认为null

    public static SingleObj getInstance(){
        if(singleObj==null){//只有第一次调用时,才需要同步判断(此时instance未初始化,为null)。一旦instance初始化完成,就不需要了(重要!!!)
            
            //将这个类对象作为锁,谁得到这个类对象谁就可以执行其中的代码
            synchronized (SingleObj.class){
                if(singleObj==null){
                    singleObj = new SingleObj();
                }
            }
        }

        return singleObj;
    }
}

//启动5个线程,进行启动,并都去获得懒汉式的单例对象,会发现对象都相同
class Test{
    public static void main(String[] args) {
        for (int i = 0; i < 5; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    SingleObj obj = SingleObj.getInstance();
                    System.out.println(obj);
                }
            }).start();
        }
    }
}
控制台输出:
com.hr.singleInstance.SingleObj@8a284c4
com.hr.singleInstance.SingleObj@8a284c4
com.hr.singleInstance.SingleObj@8a284c4
com.hr.singleInstance.SingleObj@8a284c4
com.hr.singleInstance.SingleObj@8a284c4

原理:只要有一个线程创建好了SingleObj对象,那么其他的线程将不会执行创建对象代码,将会直接返回第一个线程创建好的对象

防止指令重排

在上述DCL懒汉式基础上进一步改进:

private static volatile SingleObj singleObj;//懒汉式,默认为null,防止指令重排

    public static SingleObj getInstance(){
        if(singleObj==null){
            //将这个类对象作为锁,谁得到这个类对象谁就可以执行其中的代码
            synchronized (SingleObj.class){
                if(singleObj==null){
                    singleObj = new SingleObj();//不是一个原子性操作,而是三步操作
                    /*
                        执行上述new 构造器()底层会有三步实现:
                        1、分配内存空间
                        2、执行构造方法,初始化对象
                        3、将引用指向内存空间

                        步骤应该是从上至下的,但是也有可能不会按照上述顺序,假设线程一执行顺序为1-						  -->3--->2

                        并假设第二个线程在线程一执行到第3步时获得了锁,此时内存空间中还没有对象,						 那么线程二直接返回的对象可能为null

                        这种现象就叫指令重排
                        为了防止指令重排,需要使用volatile关键字

                        volatile:在一个对象前加上此关键字,可以使第3步操作一定是最后执行
                     */
                }
            }
        }

        return singleObj;
    }
}

BUT!!!反射仍可以破环这种反射,通过反射将类的私有构造方法变成公开的,那么就可以无限进行创造新的对象,可以在构造方法中添加判断来解决这种破环

1.2 工厂模式

本质:实例化对象不用new,采用工厂中的方法代替

实现了实现对象和调用对象的分离

1.21 为什么要使用工厂模式

public class Test {
    public static void main(String[] args) {
//        每次生产一辆汽车,需要自己创建相应的对象,需要知道对象的参数,然后才能调用其中的方法或属性。
//        可以通过工厂模式将创建对象的工程进行包装,然后直接从工厂中获取对象
        Car c1 = new Car1();
        Car c2 = new Car2();

        c1.getName();
        c2.getName();
    }
}

1.22 简单工厂模式(静态工厂模式)

本质:将所有的车的构造方法全部放入一个CarFactory中,通过一个方法调用

public class CarFactory {
    public Car getCar(String carName){
        if(carName.equals("car1")){
            return new Car1();
        }else if (carName.equals("car2")){
            return new Car2();
        }else{
            return null;
        }
    }
}
public class Test {
    public static void main(String[] args) {
//        通过简单工厂模式将创建对象的工程进行包装,然后直接从工厂中获取对象
        CarFactory carFactory = new CarFactory();
        Car c1 = carFactory.getCar("car1");
        Car c2 = carFactory.getCar("car2");
        
        c1.getName();
        c2.getName();
    }
}

缺点:每次产生一种新的对象类型时,需要在工厂中添加相应的创建方式

1.23 工厂方法模式

本质:将工厂也变成一个接口,当新的车出现的时候,就专门给其建立一个工厂

简单工厂模式(所有车的工厂在一起) 工厂方法模式(所有车的工厂分开)

public class Car1Factory implements CarFactory{
    @Override
    public Car getCar() { return new Car1(); }
}
public class Car2Factory implements CarFactory{
    @Override
    public Car getCar() {
        return new Car2();
    }
}

public class Test {
    public static void main(String[] args) {
//        通过简单工厂模式将创建对象的工程进行包装,然后直接从工厂中获取对象
        CarFactory car1Factory = new Car1Factory();
        CarFactory car2Factory = new Car2Factory();
        Car car1 = car1Factory.getCar();
        Car car2 = car2Factory.getCar();

        car1.getName();
        car2.getName();

    }
}

这种方法使用的不多,因为增加了代码的冗余,推荐第一种

1.24 抽象工厂模式

本质:建立一个工厂(超级工厂),可以建造其他的工厂,当需要某一类汽车的工厂时,直接通过超级工厂来获取其他汽车的工厂,在通过其他汽车的工厂建造汽车,这个工厂模式使用的也不多,自行了解即可

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值