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

前言
今天是十月的最后一天!今天南京清晨的风凉意显著,就好像已经入了冬,有人穿棉袄有人穿外套!与此同时我决定把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
}

}
相当于类加载,ca1和ca2都是类对象,为同一个对象,要与类的对象有所区分。
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、工厂模式
    特点:

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

书写实体类,用来构建对象
书写.properties配置文件,存放工厂使用反射时需要的类信息
书写工厂类,创建对象
书写测试类
用一个实例演示:

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

    }
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值