Java面向对象之枚举和包装类及设计模式

枚举类型

枚举是一种特殊类。枚举是有固定实例个数的类型,我们可以把枚举理解成有固定个数实例的多例模式

枚举定义

定义枚举类型其实就是在定义一个类,只不过很多细节由编译器帮你补齐了,所以,某种程度上 enum 关键词的作用就像是classinterface

当使用enum定义枚举类型时,实际上所定义出来的类型是继承自java.lang.Enum类。而每个被枚举的成员其实就是定义的枚举类型的一个实例,它们都被默认为final。无法改变常数名称所设定的值,它们也是publicstatic的成员,这与接口中的常量限制相同。可以通过类名称直接使用它们。

枚举结构

枚举像普通的类一样可以添加属性和方法,可以为它添加静态和非静态的属性或方法

public enum SeasonEnum {
    // 注:枚举写在最前面,否则编译出错
    SPRING, SUMMER, AUTUMN, WINTER;
    private final static String position = "first";
    public static SeasonEnum getSeason(String s) {
        if(position.equals(s)) {
            return SPRING;
        }else{
            return AUTUMN;
        }
    }
}

设计带构造器的枚举

public enum Gender{
    MAN("MAN"), WOMEN("WOMEN");
    // 通过括号赋值,而且必须带有一个参构造器和一个属性跟方法,否则编译出错。赋值必须都赋值或都不赋值,不能一部分赋值一部分不赋值;如果不赋值则不能写构造器,赋值编译也出错
    private final String value;
    Gender(String value){
        this.value = value;
    }
    public String getValue(){
        return value;
    }
}

设计带抽象方法的枚举

public enum OrderState{
    CANCEL{public String getName(){return "已取消";}},
    WAITCONFIRM{public String getName(){return "待审核";}},
    WAITPAYMENT{public String getName(){return "等待付款";}},
    ADMEASUREPRODUCT {public String getName(){return "正在配货";}},
    WAITDELIVER {public String getName(){return "等待发货";}},
    DELIVERED {public String getName(){return "已发货";}},
    RECEIVED {public String getName(){return "已收货";}};
    
    public abstract String getName();
    // 此枚举类的抽象方法
}

枚举的应用

枚举是一种类型,用于定义变量,以限制变量的赋值;赋值时通过 “枚举名.值” 取得枚举中的值。

枚举类的常用API如下:

步骤序号步骤详解
values()取得所有的枚举成员实例,并以数组方式返回
compareTo()比较两个枚举对象在枚举时的顺序
ordinal()依枚举顺序得到位置索引,默认以0开始

包装类

虽然Java是面向对象的编程语言,但它所包含的8种基本数据类型却不支持面向对象的编程机制(没有属性和方法)。在Java中,很多类的方法都需要接收引用类型的对象,此时就无法将一个基本数据类型的值传入。为了解决这样的问题,JDK中提供了一系列的包装类,通过这些包装类可以将基本数据类型的值包装为引用数据类型的对象。

包装类的继承关系

Untitled Diagram.drawio.png
基本类型——包装类对照表

基本数据类型对应的包装类
byteByte
shortShort
intInteger
longLong
floatFloat
doubleDouble
charCharacter
booleanBoolean

自动装箱和自动拆箱

自动装箱:是指将基本数据类型的变量赋给对应的包装类变量

自动拆箱:是指将包装类对象类型直接赋给一个对应的基本数据类型变量

包装类的API

基本数据类型、基本数据包装类以及字符串之间的相互转换:

  1. 通过引用数据类型字符串String类的valueOf()方法可以将8种基本数据类型转换为对应的字符串类型
  2. 通过8种包装类的静态方法valueOf()既可以将对应的基本数据类型转换为包装类,也可以将变量内容匹配的字符串转换为对应的包装类(Character包装类除外)。
  3. 通过8种包装类的有参构造方法同样既可以将对应的基本数据类型转换为包装类,也可以将变量内容匹配的字符串转换为对应的包装类(Character包装类除外)。
  4. 通过8种包装类的静态方法parseXxx()可以将变量内容匹配的字符串转换为对应的基本数据类型。
  5. 包装类都重写了Object类中的toString()方法,以字符串的形式返回被包装的基本数据类型的值。

使用valueOf(String s)方法注意事项:

除了Character外,包装类都有valueOf(String s)方法,可以根据String类型的参数创建包装类对象,但参数字符串s不能为null,而且字符串必须是可以解析为相应基本类型的数据,否则虽然编译通过,但运行时会报错。

Integer i = Integer.valueOf("123");// 合法
Integer i = Integer.valueOf("12a");// 不合法

使用parseXxx(String s)方法注意事项:

除了Character外,包装类都有parseXxx(String s)的静态方法,将字符串转换为对应的基本类型的数据。参数s不能为null,而且同样必须是可以解析为相应基本类型的数据,否则虽然编译通过,但运行时会报错。

int i = Integer.parseInt("123");// 合法
Integer in = Integer.parseInt("huawei");// 不合法

设计模式

设计模式(Design pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。

设计模式的类型

根据设计模式的参考书 Design patterns - Elements of Reusable Object-Oriented Software 中所提到的,总共有23种设计模式。这些模式可以分为三大类:创建型模式、结构型模式、行为型模式

单例模式

单例模式是Java中最简单的设计模式之一。这种类型的设计模式数据创建型模式,它提供了一种创建对象的最佳方式。

这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

注意:

  1. 单例类只能有一个实例
  2. 单例类必须自己创建自己的唯一实例
  3. 单例类必须给所有其他对象提供这一实例

方式:

  • 懒汉式
  • 饿汉式

策略模式

在策略模式中,一个类的行为或算法可以在运行时更改。这种类型的设计模式属于行为型模式。

意图:定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换

主要解决:在有多种算法相似的情况下,使用if...else所带来的复杂度和难以维护

何时使用:一个系统有许多许多类,而区分它们的只是他们直接的行为

如何解决:将这些算法封装成一个一个的类,任意地替换。

关键代码:实现同一个接口。

应用实例:

  1. 诸葛亮的锦囊妙计,每一个锦囊就是一个策略
  2. 旅行的出游方式,选择骑自行车、坐汽车,每一种旅行方式都是一个策略
  3. JAVA AWT中的LayoutManager

工厂模式

工厂模式是Java中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式

在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且通过使用共同的接口来指向新创建的对象

意图:定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。

主要解决:主要解决接口选择的问题

何时使用:我们明确地计划不同条件下创建不同实例时

如何解决:让其子类实现工厂接口,返回的也是一个抽象的产品

关键代码:创建过程在其子类执行

应用实例:

  1. 您需要一辆汽车,可以直接从工厂里面提货,而不用去管这辆汽车是怎么做出来的,以及这个汽车里面的具体实现
  2. Hibernate 换数据库只需换方言和驱动就可以。

代理模式

在代理模式中,一个类代表另一个类的功能。这种类型的设计模式属于结构型模式

在代理模式中,我们创建拥有现有对象的对象,以便向外界提供功能接口

意图:为其他对象提供一种代理以控制对这个对象的访问

主要解决:在直接访问对象时带来的问题

何时使用:想在访问一个类时做一些控制

如何解决:增加中间层

关键代码:实现与被代理类组合

应用实例:

  1. 买火车票不一定在火车站买,也可以去代售点
  2. 一张支票或银行存单是账户中资金的代理。支票在市场交易中用来代替现金,并提供对签发人账号上资金的控制
  3. spring aop

门面模式

现代的软件系统都是比较复杂的,设计师处理复杂系统的一个常见方法便是将其“分而治之”,把一个系统划分为几个较小的子系统。

门面模式

  • 也叫外观模式
  • 这种类型的设计模式属于结构型模式,它向现有的系统添加一个可以访问系统的接口,来隐藏系统的复杂性
  • 这种模式涉及到一个单一的类,该类提供了客户端请求的简化方法和对现有系统类方法的委托和调用

Q.E.D.