一. 枚举类
(1)语法
public enum 枚举类名{
}
(2)适用场景:
当对象的个数已经固定,并有限时,例如:性别,星期等等()
举例:
//定义一个枚举类
public enum Sex {
//男性
MALE,
//女性
FEMALE
}
(3)枚举类中常用的方法
//枚举类中常用的方法
//1.获取枚举类中对象的序号,序号从0开始
System.out.println(Sex.MALE.ordinal());//0
System.out.println(Sex.FEMALE.ordinal());//1
//2.枚举类和字符串的转换
//把枚举对象转为字符串
System.out.println(Sex.MALE.name());//MALE
//把字符串转为枚举对象
Sex female = Sex.valueOf("FEMALE");
//虚拟机中的枚举对象只有一份,可以用==来比较
System.out.println(Sex.valueOf("MALE") == Sex.MALE);//true
//3.打印所有的枚举对象
for (Sex sex : Sex.values()) {
System.out.println(sex);
}
(4)枚举类中也可以有方法,构造方法,属性, 但 构造方法不能是公共的
枚举类不能继承
public enum Sex {
// 男性
MALE("男"),
// 女性
FEMALE("女");
// 方法,构造方法...
public String test() {
return "ok";
}
private String cnName;
public String cnName() {
return this.cnName;
}
// 构造方法不能是公共的
Sex(String cnName) {
this.cnName = cnName;
}
}
二.设计模式
编程中的一些套路,让我们的代码实现特定的目的,结构上更加优秀 简称 GOF (group of Four) -- 23种
1.单例模式 (Singleton)
(1)定义:虚拟机中这个类只有一个实例(一个对象)
(2)实现方式
方法1:饿汉式单例 (一开始就创建好)
public class Singleton1 {
/**
* 让构造方法私有,别人就没法创建此类的实例了
*/
private Singleton1() {
}
/**
* 自己创建这个实例
*/
private static final Singleton1 ME = new Singleton1();
/**
* 获取唯一实例
* @return
*/
public static Singleton1 getInstance() {
return ME;
}
}
方法2:懒汉式单例 (用到时才创建,用不到不创建)
在多线程下为了保证真正的单例,需要使用sychronized同步
public class Singleton2 {
private Singleton2() {
}
private static Singleton2 ME;
// 线程1 , 线程2
/*
线程1 锁住了 Singleton2.class 对象
if (ME == null) {
线程2 等待 线程1 释放 Singleton2.class 对象上的锁
*/
public static synchronized Singleton2 getInstance() {
// 当一次调用时ME == null为真, 当后续调用时ME == null为假,就不会执行创建对象的操作了
if (ME == null) {
ME = new Singleton2();
}
return ME;
}
}
方法3:用枚举类实现单例,属于饿汉式单例
public enum Singleton3 {
ME;
public void m1() {
}
}
方法4:懒汉式的更佳实现
public class Singleton4 {
static{
System.out.println("Singleton4类被加载了");
}
private Singleton4() {
}
// holder 拥有, 由静态内部类创建了他的唯一实例
private static class Holder {
static{
System.out.println("Holder类被加载了");
}
static Singleton4 ME = new Singleton4();
}
public static Singleton4 getInstance() {
return Holder.ME;
}
public static void test() {
System.out.println("Singleton4其它方法");
}
}
(3)破坏单例的办法:
1) 反射可以调用私有构造
2) 反序列化可以破坏单例 (可以阻止)
2.享元模式 (flyweight)
提倡重用已有的对象,而不是创建新的对象
Integer的享元范围 -128 ~ 127 ,Byte, Short, Charater, Long也是
举例:
System.out.println(Integer.valueOf(1) == Integer.valueOf(1)); // true
System.out.println(Integer.valueOf(100) == Integer.valueOf(100));// true
System.out.println(Integer.valueOf(200) == Integer.valueOf(200));// false
3.原型模式 (prototype)
(1)定义:根据已有对象来创建新的对象, 克隆(不是通过new创建对象)
(2)实现方式: 实现Cloneable接口,重写Object类中的clone()
(3)使用场景: 当对象属性很多,希望新的对象的大部分属性从原有对象复制而来
public class User implements Cloneable {
private String name;
private int age; // 18 --> 18
private Date birthday; // #1234 --> #1234
//...getXXX()和setXXX()
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
(4)浅拷贝和深拷贝
刚才的Cloneable实现的是浅拷贝,也就是说,对象的属性仅仅是复制了地址,没有把内容新复制一份
深拷贝是指所有的内容都得是全新的
4.建造器模式(Builder)
(1)目的:让我们创建对象的过程更为灵活。适用于一步一步构建一个较为复杂的对象
public class Person {
private String name;
private String sex;
private Integer weight;
private Integer height;
// 建造器
public static class PersonBuilder{
//建造器属性跟Person类属性相同
private String name;
private String sex="男";
private Integer weight=50;
private Integer height;
// 返回值类型不再是void 而是建造器类型本身
public PersonBuilder name(String name) {
this.name = name;
return this;
}
public PersonBuilder sex(String sex) {
this.sex = sex;
return this;
}
public PersonBuilder weight(Integer weight) {
this.weight = weight;
return this;
}
public PersonBuilder height(Integer height) {
this.height = height;
return this;
}
//建造器提供一个build方法
public Person build() {
// 需要的信息收集齐了
return new Person(this.name,this.sex,this.weight,this.height);
}
}
private Person(String name, String sex, Integer weight, Integer height) {
this.name = name;
this.sex = sex;
this.weight = weight;
this.height = height;
}
public String getName() {
return name;
}
public String getSex() {
return sex;
}
public Integer getWeight() {
return weight;
}
public Integer getHeight() {
return height;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", sex='" + sex + '\'' +
", weight=" + weight +
", height=" + height +
'}';
}
}
(2)jdk的体现:StringBuilder(可以不断的调用append()方法,创建一个很复杂的字符串对象,最后调用tostring()转换成一个字符串)
5.迭代器模式(iterator)
定义:以一种一致的对集合内的元素进行遍历,而不用在乎集合内的数据结构
ArrayList 数组
LinkedList 链表
HashSet 数组+链表
TreeSet 二叉搜索树-》红黑树
for(Object o : 集合)本质都是调用迭代器
Iterator iter = 集合.iterator();
while(iter.hasNext()) {
iter.next();
}
6.策略模式 (Strategy)
java 集合或数组的排序算法
Collections.sort
Arrays.sort
排序的是:基本类型 双基点快速排序
对象类型 TimSort (早期使用归并排序)
规模小 插入排序
排序算法是固定的,排序的规则能否固定?--》 不能
把排序的规则抽取出来,形成比较器接口(Comparator),不同比较器的实现就称为策略
举例:
public class TestStrategy {
public static void main(String[] args) {
List<Student> list = new ArrayList<>();
list.add(new Student("zhangsan", 18));
list.add(new Student("lisi", 20));
list.add(new Student("wangwu", 16));
list.add(new Student("zhaoliu", 22));
list.add(new Student("zhaoliu", 20));
// 按年龄排
Collections.sort(list, (a, b) -> a.getAge() - b.getAge() );
System.out.println(list);
// 按名字排
Collections.sort(list, (a, b) -> a.getName().compareTo(b.getName()) );
System.out.println(list);
// 先按名字,再按年龄
Collections.sort(list, (a, b) -> {
int x = a.getName().compareTo(b.getName());
if(x != 0) {
return x;
} else {
return a.getAge() - b.getAge();
}
} );
System.out.println(list);
}
}
class Student {
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
策略模式体现了open close 开闭原则
算法不能改-- 体现的是close原则
比较器可以改 -- 体现的是open原则
7.简单工厂模式
建立一个工厂类,对实现了同一接口的一些类进行实例的创建。
简单工厂模式的实质是由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类(这些产品类继承自一个父类或接口)的实例。
举例:
人类在世界分为男人和女人,首先定义一个Human产品的抽象接口
public interface Human {
public void say();
}
然后定义男人和女人,同样都有说话的方法
public class Man implements Human {
@Override
public void say() {
System.out.println("男人");
}
}
public class Woman implements Human {
@Override
public void say() {
System.out.println("女人");
}
}
最后写一个工厂类,用来创造男人和女人。使用逻辑判断的方式实现的。
public class SimpleFactory {
public static Human makeHuman(String type){
if(type.equals("man")){
Human man = new Man();
return man;
}else if(type.equals("woman")){
Human woman = new Woman();
return woman;
}else {
System.out.println("生产不出来");
return null;
}
}
}
测试类
public static void main(String[] args) {
Human man = SimpleFactory.makeHuman("man");
man.say();
Human woman = SimpleFactory.makeHuman("woman");
woman.say();
Human thirdman = SimpleFactory.makeHuman("火星人");
}
运行结果:
男人
女人
生产不出来