单例模式、多例模式、枚举、工厂模式

第一章 单例设计模式

1.1 单例设计模式的概述

引入
public class Person{
    
}
public class Test{
    public static void main(String[] args){
        Person p1 = new Person();
        Person p2 = new Person();
        Person p3 = new Person();
        //...
    }
}
单例设计模式的作用

单例模式,是一种常用的软件设计模式,属于创建型模式。通过单例模式可以保证系统中,应用该模式的这个类只有一个实例。即一个类只有一个对象实例。

单例设计模式实现步骤
  1. 将构造方法私有化,使其不能在类的外部通过new关键字实例化该类对象。
  2. 在该类内部创建一个唯一的对象
  3. 定义一个静态方法返回这个唯一对象。
单例设计模式的类型

根据实例化对象的时机单例设计模式又分为以下两种:

  1. 饿汉单例设计模式
  2. 懒汉单例设计模式

1.2 饿汉式单例设计模式

  • 概述: 饿汉单例设计模式就是使用类的时候已经将对象创建完毕,不管以后会不会使用到该实例化对象,先创建了再说。很着急的样子,故被称为“饿汉模式”。

  • 代码如下:

    public class Person {
        // 1.将构造方法私有化,防止在类的外部通过new调用构造方法创建对象
        private Person(){
    
        }
    
        // 2.在类的内部创建一个唯一的对象
        private static final Person p = new Person();
    
        // 3.提供公共的静态方法用来获取该类的唯一对象
        public static Person getInstance(){
            return p;
        }
        
        public static void method(){}
    }
    
    public class Test {
        public static void main(String[] args) {
           // Person.method();// 已经创建了该类的唯一对象
    
            System.out.println(Person.getInstance());
            System.out.println(Person.getInstance());
            System.out.println(Person.getInstance());
            System.out.println(Person.getInstance());
            System.out.println(Person.getInstance());
        }
    }
    结果: 地址值相同
    com.geekly.demo1_饿汉式单例设计模式.Person@4554617c
    com.geekly.demo1_饿汉式单例设计模式.Person@4554617c
    com.geekly.demo1_饿汉式单例设计模式.Person@4554617c
    com.geekly.demo1_饿汉式单例设计模式.Person@4554617c
    com.geekly.demo1_饿汉式单例设计模式.Person@4554617c
    

1.3 懒汉式单例设计模式

  • 概述: 懒汉单例设计模式就是调用getInstance()方法时对象才被创建,先不急着创建出对象,等要用的时候才创建对象。不着急,故称为“懒汉模式”。

  • 代码如下:

    public class Person {
        // 1.将构造方法私有化,防止在类的外部通过new调用构造方法创建对象
        private Person() {
    
        }
    
        // 2.定义一个静态的成员变量,用来存储创建的该类的唯一对象
        private static Person p;
    
        // 3.在该类的内部创建该类的唯一对象(多线程环境下会造成数据污染,要加锁)
        public static synchronized Person getInstance() {
            // 判断
            // 如果是第一次调用该方法,就创建该类的对象
            if (p == null) {
                p = new Person();
            }
            // 如果不是第一次调用该方法,就返回第一次调用的时候创建的对象
            return p;
        }
    
        public static void method(){}
    }
    
    
    public class Test {
        public static void main(String[] args) {
            //Person.method();
             System.out.println(Person.getInstance());
             System.out.println(Person.getInstance());
             System.out.println(Person.getInstance());
             System.out.println(Person.getInstance());
             System.out.println(Person.getInstance());
        }
    }
    执行结果:
    com.geekly.demo2_懒汉式单例设计模式.Person@4554617c
    com.geekly.demo2_懒汉式单例设计模式.Person@4554617c
    com.geekly.demo2_懒汉式单例设计模式.Person@4554617c
    com.geekly.demo2_懒汉式单例设计模式.Person@4554617c
    com.geekly.demo2_懒汉式单例设计模式.Person@4554617c
    
  • 注意: 懒汉式单列设计模式在多线程的情况下很容易出现创建多个对象,所以getInstance方法需要加锁

第二章 多例设计模式

2.1 多例设计模式

多例设计模式的作用

多例模式,是一种常用的软件设计模式,属于创建型模式。通过多例模式可以保证系统中,应用该模式的类有固定数量的对象产生。

说白了,多例设计模式就是保证使用该模式的类会有固定数量的该类对象产生

实现步骤

​ 1.创建一个类, 将构造方法私有化,使其不能在类的外部通过new关键字实例化该类对象。

​ 2.在该类内部产生固定数量的对象

​ 3.提供一个静态方法来随机获取一个该类的对象

实现代码
public class Person {

    // 1.将构造方法私有化,防止外界通过new调用构造方法创建对象
    private Person(){

    }

    // 2.定义一个ArrayList集合,用来存储Person对象
    private static ArrayList<Person> list = new ArrayList<>();

    // 3.在类的内部创建固定数量的对象--->静态代码块
    static {
        for (int i = 0; i < 3; i++) {
            // 创建Person对象
            Person p = new Person();
            // 存储Person对象
            list.add(p);
        }
    }

    // 3.提供一个公共的静态方法用来随机获取一个该类的对象
    public static Person getInstance(){
        // 创建Random对象
        Random r = new Random();
        // 生成随机数--->集合索引的范围
        int index = r.nextInt(list.size());
        // 根据索引获取元素
        Person p = list.get(index);
        // 返回
        return p;
    }
}
public class Test {
    public static void main(String[] args) {
        System.out.println(Person.getInstance());
        System.out.println(Person.getInstance());
        System.out.println(Person.getInstance());
        System.out.println(Person.getInstance());
        System.out.println(Person.getInstance());
        System.out.println(Person.getInstance());
        System.out.println(Person.getInstance());
        System.out.println(Person.getInstance());
        System.out.println(Person.getInstance());
        System.out.println(Person.getInstance());
        System.out.println(Person.getInstance());
    }
}
执行结果:
com.geekly.demo3_多例设计模式.Person@74a14482
com.geekly.demo3_多例设计模式.Person@74a14482
com.geekly.demo3_多例设计模式.Person@1540e19d
com.geekly.demo3_多例设计模式.Person@677327b6
com.geekly.demo3_多例设计模式.Person@74a14482
com.geekly.demo3_多例设计模式.Person@677327b6
com.geekly.demo3_多例设计模式.Person@677327b6
com.geekly.demo3_多例设计模式.Person@677327b6
com.geekly.demo3_多例设计模式.Person@677327b6
com.geekly.demo3_多例设计模式.Person@677327b6
com.geekly.demo3_多例设计模式.Person@1540e19d

第三章 枚举

3.1 枚举的定义和使用

不使用枚举存在的问题

假设我们要定义一个人类,人类中包含姓名和性别。通常会将性别定义成字符串类型,效果如下:

public class Person {
    private String name;
    private String sex;

    public Person() {
    }

    public Person(String name, String sex) {
        this.name = name;
        this.sex = sex;
    }
}
public class Demo01 {
    public static void main(String[] args) {
        Person p1 = new Person("张三", "男");
        Person p2 = new Person("张三", "abc"); // 因为性别是字符串,所以我们可以传入任意字符串
    }
}

不使用枚举存在的问题:可以给性别传入任意的字符串,导致性别是非法的数据,不安全。

枚举的概念

枚举是一种引用数据类型,java中枚举的底层是一个有固定个数对象的"特殊类"(多例设计模式)。所以如果某种类型的数据有固定个值,就可以定义为枚举类型。比如性别, 季节,方向。

定义枚举的格式
  • 格式:

    public enum 枚举名{
        枚举值,枚举值,枚举值,... // 枚举值全部字母大写,多个枚举值使用逗号隔开
    }
    
  • 案例:

    //变大写:ctrl+shift+u
    // 性别枚举类型
    public enum Gender {
        // 枚举值
        MAN,WOMAN,YAO
    }
    
    // 季节枚举类型
    public enum Season {
        SPRING,
        SUMMER,
        AUTUMN,
        WINTER
    }
    
    // 方向枚举类型
    public enum Direction {
        UP,
        DOWN,
        LEFT,
        RIGHT
    }
    
枚举的使用
  • 格式: 枚举名.枚举值

  • 案例:

    public class Person {
        String name;
        // 性别枚举类型的成员变量
        Gender gender;
    
        public Person(String name, Gender gender) {
            this.name = name;
            this.gender = gender;
        }
        @Override
        public String toString() {
            return "Person{" +
                    "name='" + name + '\'' +
                    ", gender=" + gender +
                    '}';
        }
    }
    
    public class Test {
        public static void main(String[] args) {
            // 枚举使用: 枚举名.枚举值
    
            // 创建Person对象
            Person p = new Person("张三", Gender.MAN);
            System.out.println("p:" + p);
    
            // 修改p对象的性别为妖
            p.gender = Gender.YAO;
            System.out.println("p:" + p);
        }
    }
    执行结果:
    p:Person{name='张三', gender=MAN}
    p:Person{name='张三', gender=YAO}
    

3.2 枚举中的其他内容

  • 枚举的本质是一个使用了多例设计模式的类,所以枚举中还可以有成员变量,成员方法,构造方法等

  • 枚举的本质是一个类,我们刚才定义的Sex枚举最终效果如下:

    public enum Gender {
        // 枚举值
        MAN(10),// Gender MAN = new Gender(10)
        WOMAN(20),
        YAO(30);
    
    
        // 成员变量
        int num;
    
        // 构造方法,必须私有化
        private Gender(int num){
            this.num = num;
        }
    
        // 成员方法
        public void method(){
            System.out.println("成员方法method...");
        }
    
    }
    
    public class Test {
        public static void main(String[] args) {
            // 定义一个Gender类型的变量g1,并赋值
            Gender g1 = Gender.MAN;
            System.out.println("num: "+g1.num);// num: 10
            g1.method();// 成员方法method...
        }
    }
    

第四章 工厂设计模式

4.1 工厂模式的概述

工厂模式的介绍

​ 工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。之前我们创建类对象时, 都是使用new 对象的形式创建, 除new 对象方式以外, 工厂模式也可以创建对象.

耦合度: 类与类之间的关系,如果关系比较强,高耦合, 如果关系比较弱,低耦合(开发)

需求: 有10个类,需要在10个测试类中,分别创建这10个类的对象

以前: 直接通过new 来创建 —>每一个测试类都需要和这10个类进行关联–(耦合度高)

工厂模式: 定义一个工厂类,专门用来创建这10个类的对象, 并提供获取对象的方法,那这个时候测试类只需要跟工厂类关联即可----> 低耦合

工厂模式的作用

将获取对象的代码与要创建对象的代码进行分开,获取对象的代码不需要直接创建对象,也就不需要关心创建对象时需要的数据。只需要通过工厂类获取对象即可。

  • 解决类与类之间的耦合问题
案例演示
需求
  1. 编写一个Car接口, 提供run方法

  2. 编写一个Falali类实现Car接口,重写run方法

  3. 编写一个Benchi类实现Car接口,重写run方法

    提供一个工厂类,可以用来生产汽车对象

实现代码

1.编写一个Car接口, 提供run方法

public interface Car {
    void run();
}

2.编写一个Falali类实现Car接口,重写run方法

public class Falali implements Car {
    @Override
    public void run() {
        System.out.println("法拉利正在以300迈的速度行驶...");
    }
}

3.编写一个Benchi类实现Car接口

public class Benchi implements Car {
    @Override
    public void run() {
        System.out.println("奔驰正在以200迈的速度行驶...");
    }
}

4.提供一个CarFactory(汽车工厂),用于生产汽车对象

// 工厂类: 专门创建对象
public class CarFactory {

    public static Car createCar(String brand){
        if (brand.equalsIgnoreCase("Falali")){
            // 创建法拉利汽车对象,并返回
            return new Falali();

        }else if (brand.equalsIgnoreCase("Benchi")){
            // 创建奔驰汽车对象,并返回
            return new Benchi();

        }else{
            return null;
        }

    }
}

5.定义CarFactoryTest测试汽车工厂

public class Test {
    public static void main(String[] args) {
        // 不使用工厂设计模式--->得到法拉利对象,奔驰对象
        // Falali fl = new Falali();
        // Benchi bc = new Benchi();


        // 使用工厂设计模式--->得到法拉利对象,奔驰对象
        Car car1 = CarFactory.createCar("Falali");
        car1.run();

        Car car2 = CarFactory.createCar("Benchi");
        car2.run();
    }
}

第五章 Lombok

5.1 Lombok的使用

lombok介绍
  • lombok可以使用注解的方式让一些代码变的简洁 方便
  • 实体类中有一些固定的代码:构造方法,getter/setter、equals、hashcode、toString方法都是固定的,写出来看着比较麻烦。而Lombok能通过注解的方式,在编译时自动为属性生成这些代码。
lombok常用注解
  • @Getter和@Setter

    • 作用:生成成员变量的get和set方法。
    • 写在成员变量上,指对当前成员变量有效。
    • 写在类上,对所有成员变量有效。
    • 注意:静态成员变量无效。
  • @ToString:

    • 作用:生成toString()方法。
    • 该注解只能写在类上。
  • @NoArgsConstructor和@AllArgsConstructor

    • @NoArgsConstructor:无参数构造方法。
    • @AllArgsConstructor:满参数构造方法。
  • 注解只能写在类上。

  • @EqualsAndHashCode

    • 作用:生成hashCode()和equals()方法。
    • 注解只能写在类上。
  • @Data

    • 作用: 生成setter/getter、equals、hashCode、toString方法,如为final属性,则不会为该属性生成setter方法。

    • 注解只能写在类上。

  • 案例:

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public class Person {
        private String name;
        private int age;
    
        // 构造方法--空参,满参
        // set\get
        // toString
        // equals and hashCode
    }
    
    
    public class Test {
        public static void main(String[] args) {
            // 创建Person对象
            Person p1 = new Person();
            p1.setName("张三");
            p1.setAge(18);
            System.out.println(p1.getName() + "," + p1.getAge());
            System.out.println("p1:" + p1);
    
            Person p2 = new Person("张三",18);
            System.out.println(p1.equals(p2));// true
            System.out.println(p1.hashCode());// 45721950
            System.out.println(p2.hashCode());// 45721950
        }
    }
    

总结

	1.单例设计模式
    2.多例设计模式
    3.定义和使用枚举
    4.工厂设计模式
        
- 能够说出单例设计模式的好处
  保证使用该模式设计的类只有1个对象产生
  步骤:
	1.将构造方法私有化
    2.在类的内部创建该类的唯一对象
    3.提供公共静态方法用来获取该类的唯一对象
        
- 能够说出多例模式的好处
  保证使用该模式设计的类只有固定数量对象产生
  步骤:
	1.将构造方法私有化
    2.在类的内部创建该类固定数量的对象
    3.提供公共静态方法用来获取该类中创建的任意对象 
        
- 能够定义枚举
  格式:
		public enum 枚举名{
            枚举值,枚举值,...
        }
  使用: 枚举名.枚举值
      
- 能够使用工厂模式编写java程序
   定义一个类,提供一个静态方法,在静态方法中创建类的对象并返回   
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
单例模式的扩展及应用。 编写一个类LimitInstanceClass,该类最多可以实例化指定个数实例。实例的个数用配置文件InstanceLimit.cfg指定。例如,如果InstanceLimit.cfg的内容为2,则LimitInstanceClass最多可以同时存在2个对象。LimitInstanceClass的对象有一个整型成员变量id,保存对象的编号;有一个boolean型变量isBusy,如果该变量的值为true,表示该对象正在被使用,否则该对象空闲;如果存在空闲的对象,则调用LimitInstanceClass的getInstance()方法会返回一个空闲对象,同时将该对象的isBusy置为true;如果不存在空闲对象则返回null。LimitInstanceClass有一个release()方法,该方法将对象的isBusy置为false。LimitInstanceClass还有一个String类型的成员变量accessMessage,以及一个成员方法writeAccessMessage(String message),该方法将参数message追加到accessMessage。LimitInstanceClass的printAccessMessage()方法输出accessMessage的内容。 编写一个线程类AccessLimitInstanceClassThread,在其run()方法中获取一个LimitInstanceClass对象,调用获得的对象的writeAccessMessage(String message)将自己的线程名写入accessMessage,随机休眠0-5秒,再调用printAccessMessage(),最后调用release()方法。 编写一个UseLimitInstanceClass类,在其main方法中实例化10个AccessLimitInstanceClassThread线程对象,并启动各个线程。 设置InstanceLimit.cfg的内容为3,写出你的程序的运行结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值