枚举类、设计模式

**

枚举类

**
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其它方法");
    }
}

破坏单例的办法:

  1. 反射可以调用私有构造
  2. 反序列化可以破坏单例 (可以阻止)

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)比较与使用场景
比较:第一种如果传入的字符串有误,不能正确创建对象,第三种相对于第二种,不需要实例化工厂类,所以,大多数情况下,我们会选用第三种——静态工厂方法模式
使用场景:凡是出现了大量的产品需要创建,并且具有共同的接口时,可以通过工厂方法模式进行创建。

你可能感兴趣的:(枚举类、设计模式)