Java设计模式之单例模式与工厂模式

Posted 微凉秋意

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java设计模式之单例模式与工厂模式相关的知识,希望对你有一定的参考价值。

✅作者简介:热爱后端语言的大学生,CSDN内容合伙人
✨精品专栏:C++面向对象
🔥系列专栏:JavaSE精品总结

文章目录


  前言

国庆节快乐!今天家里的风很凉爽,就好像在为国庆而欢呼!与此同时我决定把Java的设计模式总结一番,为以后能够书写清晰的项目结构打下基础。


1、设计模式概念及分类

简单来说设计模式是被广大程序员们总结并认可的编码套路,其中最常用的莫过于单例模式工厂模式,而单例模式也有更加细的分类,一起来学习一下这些模式的用法和特点吧。

2、单例模式

  • 一个类只能被实例化出来一个对象

2.1、饿汉式

  • 无论如何,都会创建出来一个对象
  • 思路:
    在类中直接实例化一个用来返回的对象,再为外界提供一个获取该对象的方法
  • 缺点:有可能造成空间浪费

代码解释:

/**
 * 单例模式-饿汉式
 */
public class ClassA 
    //唯一的、全局的、私有的、用来返回的对象实例
   private static ClassA ca=new ClassA();

    //方法:用来被外界调用,从而获取该类的唯一实例
    //static:为了使外界直接通过类名调用该方法
    public static ClassA getClassA()
        return ca;
    

   //私有化构造:避免外界通过构造创建该类的对象
   private ClassA()



public class Test 
    public static void main(String[] args) 
        ClassA ca1=ClassA.getClassA();
        ClassA ca2=ClassA.getClassA();
        System.out.println(ca1==ca2);//true
    

相当于类加载,ca1ca2都是类对象,为同一个对象,要与类的对象有所区分。

2.2、懒汉式

  • 思路:只有当需要创建唯一实例时,才会在对应方法中进行实例化
    • 使用synchronized来同步方法
  • 缺点:同步方法效率太慢,线程效率低

代码解释:

/**
 * 单例模式-懒汉式
 */
public class ClassB 
    //声明用来返回的对象引用
    private static ClassB cb=null;

    //synchronized:避免线程安全问题
    public synchronized static ClassB getClassB()
        if (cb==null)//非空判断,避免重复创建
            cb=new ClassB();
        
        return cb;
    

    //私有化构造
    private ClassB()

这里利用了synchronized来防止重复创建实例化对象:如果事先没有创建,那就新创建,不会浪费空间。

2.2.1、懒汉式进阶版

  • 思路:在保证线程安全的基础上,最大程度提高线程效率
  • 使用synchronized来同步代码块

代码演示:

/**
 * 单例模式-懒汉式进阶版
 */
public class ClassB2 
    //声明用来返回的对象引用
    private static ClassB2 cb=null;

    //synchronized:避免线程安全问题
    public static ClassB2 getClassB2()
        if (cb==null)//非空判断,避免重复创建
            synchronized (ClassB2.class)
                if (cb==null)//二次校验,如果出现了线程安全问题,最大程度保证数据安全
                    cb=new ClassB2();
                
            
        
        return cb;
    

    //私有化构造
    private ClassB2()

同步代码块会使程序运行效率提升,因为此时只需时间片就可以执行此线程。

2.2.2、懒汉式之懒加载

  • 思路:在懒汉式的基础上,将获取自己类实例的任务交给静态内部类完成
public class ClassC 
    //声明用来返回的对象引用
    private static ClassC cc=null;

    //静态内部类:获取ClassC的唯一实例
    private static class ClassC2
        //synchronized:避免线程安全问题
        public static ClassC get()
            if (cc==null)//非空判断,避免重复创建
                synchronized (ClassC.class)
                    if (cc==null)//二次校验,如果出现了线程安全问题,最大程度保证数据安全
                        cc=new ClassC();
                    
                
            
            return cc;
        
    

    public static ClassC getClassC()
        return  ClassC2.get();
    
    
    //私有化构造
    private ClassC()

这种方式效果跟懒汉式的进阶类似,只不过是将加载交给了静态内部类,效率更高。

3、工厂模式

特点:

  • 常用于框架
  • 自身不再直接创建对象,交给 “工厂” 完成,需要对象时直接调用工厂的指定方法获取

步骤:

  1. 书写实体类,用来构建对象
  2. 书写.properties配置文件,存放工厂使用反射时需要的类信息
  3. 书写工厂类,创建对象
  4. 书写测试类

用一个实例演示:

3.1、书写实体类

public class Student 
    private String name;
    private int age;
    private double score;
    
    //此处省略getter与setter方法

    public Student() 
    

    public Student(String name, int age, double score) 
        this.name = name;
        this.age = age;
        this.score = score;
    

    @Override
    public String toString() 
        return "Student" +
                "name='" + name + '\\'' +
                ", age=" + age +
                ", score=" + score +
                '';
    

3.2、新建配置文件.properties

  1. 右键项目名创建一个后缀名为.properties的配置文件
  2. 文件内容:
    • 键(自定义)=值(类的全限定名)
    • 例如:StudentClassName=com.bz.entity.Student
  3. 结构特点:
    1. 键不可重复
    2. 等号左右无双引号
    3. 整条语句不要存在多余空格
    4. 末尾无分号
    5. 一行只能有一个键值对

3.3、书写工厂类并创建对象

/**
 * 工厂类
 */
public class MyFactory 
    //书写获取Student实例的方法
    //static:方便直接通过类名调用
    public static Student getStudent()
        Student stu=null;
        try (
                //创建字节输入流对象
                FileInputStream fis = new FileInputStream("Factory.properties");
                //添加缓冲流
                BufferedInputStream bis = new BufferedInputStream(fis);
        ) 
            //创建用来接收配置文件信息的Properties集合
            Properties p = new Properties();
            //通过load方法将配置文件读取值集合中
            p.load(bis);
            //获取全限定名
            String str= p.getProperty("StudentClassName");
            //获取类对象
            Class c = Class.forName(str);
            //利用无参构造构建类的对象
            stu=(Student) c.newInstance();

        catch (FileNotFoundException e)
            System.out.println("文件路径不正确");
        catch (IOException e)
            System.out.println("读取失败");
        catch (Exception e)
            System.out.println("未知异常!");
            e.printStackTrace();
        

        return stu;
    

3.4、对工厂类测试

public class TestMyFactory 
    public static void main(String[] args) 
        //利用工厂获取学生对象
        Student stu = MyFactory.getStudent();
        stu.setName("张三");
        stu.setAge(20);
        stu.setScore(78);
        System.out.println(stu);
    


到这里有关设计模式单例模式与工厂模式就分享结束了,最后祝大家国庆节high起来,心情愉快!

以上是关于Java设计模式之单例模式与工厂模式的主要内容,如果未能解决你的问题,请参考以下文章

java中的设计模式之单例模式工厂模式

Java学习:java中的设计模式之单例模式工厂模式

java设计模式之单例模式

Java设计模式之单例模式

设计模式之单例模式

JAVA设计模式之单例模式