Java进阶之设计模式&正则表达式
一、设计模式
1.1 设计模式概述
设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。
使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。
总体来说设计模式分为三大类:
-
创建型模式(五种):工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式
-
结构型模式(七种):适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式
-
行为型模式(十一种):策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式
这里我们学习其中单例模式和工厂模式两种。
1.2 单例模式
单例:“一个实例”,指在程序运行过程中,类最多只能产生一个“实例(对象)”。
如Windows系统中的回收站,在系统运作过程中,任何位置启动的"回收站"都是同一个对象。
单例模式有两种:
- 懒汉式【后创建对象】
- 饿汉式【先创建对象】
/*
懒汉式,需要时才创建对象
*/
public class Dog {
//定义Dog类型的变量
private static Dog dog = null;
private Dog() {
}
/*
提供静态方法,用来获取Dog对象
*/
public static synchronized Dog getDog() {
//当调用getDog方法时,判断变量dog是否是null,如果dog是null,那么就创建一个Dog对象赋值给成员变量dog
if (dog == null) {
dog = new Dog();
}
//创建Dog对象,并返回
return dog;
}
}
/*
饿汉式,一开始就创建对象
*/
public class Cat {
//将构造方法私有,防止外界使用new关键字创建对象
private Cat() {
}
//提供静态的属性,并创建对象【因为该属性是静态的,所以这段代码只执行一次,只创建一个Cat对象】
private static Cat cat = new Cat();
//提供静态方法,用来获取对象
public static Cat getCat() {
return cat;
}
}
1.2.1 单例模式衍生——多例模式
多例模式不是正式定义的设计模式,是单例模式的衍生物。
多例:“固定数量的实例”,指在程序运行过程中,类最多只能产生固定数量的“实例(对象)”。
如在一个扑克游戏中,一个"扑克类"只能产生54个对象。
/*
多例模式,要求程序中的Person只能创建3个对象
*/
public class Person {
//在类中将构造方法私有,让外界无法直接创建对象
private Person() {
}
//创建集合,用来保存程序中所有的Person对象。
private static List<Person> list = new ArrayList<>();
//定义一个静态代码块,在静态代码块中创建Person对象,并添加到集合中。
static {
for (int i = 0; i < 3; i++) {
list.add(new Person());
}
}
//定义方法,用来随机获取程序中的Person对象
public static Person getPerson() {
//生成随机的索引
Random r = new Random();
int randomIndex = r.nextInt(list.size());
//根据这个随机的索引从集合中获取元素然后返回
return list.get(randomIndex);
}
}
1.2.2 单例模式衍生——枚举
枚举本质就是类,枚举是多例的一种体现。
枚举是“多例模式”的简化写法,属于“语法糖”。
在枚举中我们可以给出一些属性,枚举中的每个属性都是自身的对象。
定义枚举需要关键字:enum
格式:
public enum 枚举名 {
属性,属性,属性
}
- 枚举中的属性在命名时建议全部大写,多个单词之间使用下划线隔开
- 枚举中的属性默认使用了static final进行修饰,因为使用static修饰了,所以我们可以通过枚举名直接使用里面的属性
/*
空参形式
*/
public enum Gender {
//男
BOY,
//女
GIRL
}
/*
带参形式
*/
public enum Gender {
BOY("男"),
GIRL("女");
private String title;
Gender(String title) {
this.title = title;
}
@Override
public String toString() {
return title;
}
}
public class Person {
//姓名
private String name;
//性别
private Gender gender;
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", gender=" + gender +
'}';
}
public Person() {
}
public Person(String name, Gender gender) {
this.name = name;
this.gender = gender;
}
get/set方法
}
public class Demo01Test {
public static void main(String[] args) {
//创建Person对象
Person p = new Person();
//调用set方法进行赋值
p.setName("张三");
p.setGender(Gender.BOY);
//输出
System.out.println(p);//Person{name=张三,gender=男}
}
}
1.3 工厂模式
工厂模式指不直接new某个对象,而是通过一个“工厂类”获取这个对象的对象创建方式。
工厂模式的作用是解开类和类之间的“耦合”,降低类与类之间的关联性。
利用工厂模式获取汽车对象案例
/*
小汽车类(父类)
*/
public abstract class Car {
public abstract void run();
}
/*
奥拓汽车
*/
public class AoTuo extends Car{
@Override
public void run() {
System.out.println("奥拓在慢慢跑");
}
}
/*
法拉利跑车
*/
public class FaLali extends Car{
@Override
public void run() {
System.out.println("法拉利在超速行驶");
}
}
/*
用来生产小汽车的工厂
*/
public class CarFactory {
/*
定义方法,用来获取小汽车
*/
public static Car getCar(String carName) {
//判断如果carName是法拉利,就返回法拉利对象
if (carName.equals("法拉利")) {
return new FaLali();
} else if (carName.equals("奥拓")) {
return new AoTuo();
} else {
//其他的全部返回null值
return null;
}
}
}
/*
小汽车测试类
*/
public class Demo01Test {
public static void main(String[] args) {
Car car = CarFactory.getCar("法拉利");
car.run();
}
}
二、正则表达式
正则表达式:是一个字符串,里面描述了一组规则,用来判断另一个字符串是否符合该规则。
与正则有关的方法:
boolean matches(String regex)
:根据正则表达式验证字符串是否符合规则String[] split(String regex)
:根据正则表达式切割字符串String replaceAll(String regex, String replacement)
:根据正则表达式进行替换
正则表达式的规则简单介绍:
-
[abc]:代表a或者b,或者c字符中的一个。
-
[^abc]:代表除a,b,c以外的任何字符。
-
[a-z]:代表a-z的所有小写字符中的一个。
-
[A-Z]:代表A-Z的所有大写字符中的一个。
-
[0-9]:代表0-9之间的某一个数字字符。
-
[a-zA-Z0-9]:代表a-z或者A-Z或者0-9之间的任意一个字符。
-
[a-dm-p]:a 到 d 或 m 到 p之间的任意一个字符。
-
\d
数字:[0-9] -
\D
非数字: [^0-9] -
\s
空白字符:[ \t\n\x0B\f\r] -
\S
非空白字符:[^\s] -
\w
单词字符:[a-zA-Z_0-9] -
\W
非单词字符:[^\w] -
?
0次或1次 -
*
任意次 -
+
1次或多次 -
{n}
出现n次 -
{n,}
至少n次 -
{n,m}
至少n次,最多m次
public class Demo01String {
public static void main(String[] args) {
//验证QQ号是否符合规则。要求: 必须是5-12位的数字, 首位不能是0
String qq = "124959292";
boolean flag = qq.matches("[1-9][0-9]{4,11}");
System.out.println(flag);
//验证手机号是否符合规则。 要求:必须是11位,第一位必须是1, 第二位必须是3,5,7,8,9,剩下的必须是0-9数字
String phone = "16885885";
boolean flag2 = phone.matches("1[35789][0-9]{9}");
System.out.println(flag2);
//验证邮箱 xxx@itcast.cn xxx@sina.com.cn
String email = "jags@126.com.cn.xxx";
boolean flag3 = email.matches("\\w+@\\w+(\\.\\w+)+");
System.out.println(flag3);
}
}
public class Demo02String {
public static void main(String[] args) {
String str = "aa bb cc dd";
//替换,使用*替换掉str中的空格
String newStr = str.replaceAll("\\s+", "*");
System.out.println(newStr);
//根据空格切割
String[] strArr = str.split("\\s+");
for (String s : strArr) {
System.out.println(s);
}
}
}