**
**
1.适用场景:当对象的个数已经固定,并有限时,例如:性别,星期等等
2.语法:public enum 枚举类名{},枚举类中也可以有方法,构造方法,属性,但构造方法不能是公共的,枚举类不能继承。
3.方法
获取枚举对象的序号,序号从0开始
枚举类名.枚举对象.ordinal()
// 把枚举对象转为字符串
枚举类名.枚举对象.name()
// 把字符串转为枚举对象, 虚拟机中的枚举对象只会有一份, 可以用== 来比较
枚举类名.枚举对象.valueOf(“枚举对象”) == 枚举类名.枚举对象)
// 获取枚举对象
枚举类名.枚举对象.(value)
public enum Student {
pupils,middleschoolstudent,highschoolstudent;
}
class TestStudnet{
public static void main(String[] args) {
System.out.println (Student.pupils.ordinal ());
System.out.println (Student.pupils.name());
System.out.println (Student.valueOf ("pupils")==Student.pupils);
for(Student value:Student.values ()){
System.out.println (value);
}
}
}
1.单例模式
定义:虚拟机中这个类只有一个实例(一个对象)
如何实现???
方法1:饿汉式单例:一开始就创建好
创建步骤:让构造方法私有,别人就没法创建此类的实例了,然后自己创建这个实例
public class Singleton1 {
private Singleton1() {
}
private static final Singleton1 ME = new Singleton1();
方法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:
用枚举类实现单例,属于饿汉式单例
方法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其它方法");
}
}
破坏单例的办法:
2.享元模式
思想:提倡重用已有的对象,而不是每次都创建新的对象。连线池对数据库连接对象进行了重用,这就是一种享元模式。
3.原型模式
思想:根据已有对象来创建新的对象,通过克隆来实现。
实现接口Cloneable
语法:public class 类名 implenents Cloneable{}
注意:必须重写clone()方法
使用场景:当对象属性非常多的时候,希望新的对象的大部分属性从原有对象复制过来。
public class User implements Cloneable {
private String name;
private int age;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
4.建造器模式
使用场景:实现构造方法创建对象时需要有些参数为空或者只需要部分参数时,创建多个构造方法麻烦且占用空间,这时需要用到建造器模式。
方法步骤:
(1)建造器中参数与类中相同;
(2)相当于set方法,只是返回值为自身类;
(3)用一个方法把最终对象返回。
目的:让我们创建对象的过程更加灵活,适用于一步一步构建一个较为复杂的对象。
具体表现:jdk里的StringBuilder
public class Person {
private String name;
private String sex;
private Integer weight;
private Integer height;
private Person(String name, String sex, Integer weight, Integer height) {
this.name = name;
this.sex = sex;
this.weight = weight;
this.height = height;
}
// 建造器
public static class PersonBuilder{
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;
}
public Person build() {
// 需要的信息收集齐了
return new Person(this.name,this.sex,this.weight,this.height);
}
}
5.策略模式
概念:java中集合或数组的排序算法
集合:Collections.sort
数组:Arrays.sort
基本类型:双基点快速排序
对象类型:TimSort (早期使用归并排序)
排序算法是固定的,排序的规则能否固定?–》 不能
把排序的规则抽取出来,形成比较器接(Comparator),不同比较器的实现就称为策略
open close 开闭原则
算法不能改-- 体现的是close原则
比较器可以改 – 体现的是open原则
public class TestStrategy {
public static void main(String[] args) {
List 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);
}
}
工厂方法模式(Factory Method)
(1)普通工厂模式
建立一个工厂类,对实现了同一接口的一些类进行实例的创建。
举例:以收信和发信为例
//建立接口
public interface Sender {
public void Send();
}
//发信的类实现接口Sender
public class MailSender implements Sender {
@Override
public void Send() {
System.out.println("发信");
}
}
//收信的类实现接口Sender
public class SmsSender implements Sender {
@Override
public void Send() {
System.out.println("收信");
}
}
//建工厂类
public class SendFactory {
public Sender produce(String type) {
if ("1".equals(type)) {
return new MailSender();
} else if ("2".equals(type)) {
return new SmsSender();
} else {
System.out.println("请输入正确的类型!");
return null;
}
}
}
//测试
public class FactoryTest {
public static void main(String[] args) {
System.out.println("发信请输1,收信请输2");
SendFactory factory = new SendFactory();
Sender sender = factory.produce("1");
sender.Send();
}
}
(2)多个工厂方法模式
该模式是对普通工厂方法模式的改进,在普通工厂方法模式中,如果传递的字符串出错,则不能正确创建对象,而多个工厂方法模式是提供多个工厂方法,分别创建对象。
同样以发信和收信为例
//改动工厂类
public class SendFactory {
public Sender produceMail(){
return new MailSender();
}
public Sender produceSms(){
return new SmsSender();
}
}
//测试类
public class FactoryTest {
public static void main(String[] args) {
SendFactory factory = new SendFactory();
Sender sender = factory.produceMail();
//Sender sender = factory.produce("1");
//对比普通工厂,避免了因为传递的字符串出错
//不能正确创建对象的情况
sender.Send();
}
}
(3)静态工厂方法模式
将上面的多个工厂方法模式里的方法置为静态的,不需要创建实例,直接调用即可。
//工厂类,改为静态方法
public class SendFactory {
public static Sender produceMail(){
return new MailSender();
}
public static Sender produceSms(){
return new SmsSender();
}
}
//测试类,不需要创建对象
public class FactoryTest {
public static void main(String[] args) {
Sender sender = SendFactory.produceMail();
sender.Send();
}
}
(4)比较与使用场景
比较:第一种如果传入的字符串有误,不能正确创建对象,第三种相对于第二种,不需要实例化工厂类,所以,大多数情况下,我们会选用第三种——静态工厂方法模式
使用场景:凡是出现了大量的产品需要创建,并且具有共同的接口时,可以通过工厂方法模式进行创建。