600字范文,内容丰富有趣,生活中的好帮手!
600字范文 > JAVA基础之设计模式和枚举

JAVA基础之设计模式和枚举

时间:2023-01-18 05:07:42

相关推荐

JAVA基础之设计模式和枚举

枚举

枚举是JDK1.5版本新增的特性(泛型、For-each等如今被广泛应用的特性也是由JDK1.5时所新增的),另外到了JDK1.6后switch语句支持枚举类型;

枚举的使用情况:

有的时候一个类的对象是有限且固定的,这种情况下我们使用枚举类就比较方便;

枚举就是将所有的有限的类对象先定义好;语法

public enum 枚举类名{//枚举的所有对象都必须在第一行定义好}

比如:

public enum Sex {// 男性MALE("男"),// 女性FEMALE("女");private String cnName;//可以定义方法public String cnName() {return Name;}// 构造方法不能是公共的Sex(String cnName) {Name = cnName;}}

public enum Week {MON, TUE, WED, THU, FRI, SAT, SUN}

枚举类内也可以定义属性和方法,可是是静态的和非静态的

但是构造方法必须为私有的;在定义枚举类型时我们使用的关键字是enum,与class关键字类似,只不过前者是定义枚举类型,后者是定义类类型。枚举类型Day中分别定义了从周一到周日的值,这里要注意,值一般是大写的字母,多个值之间以逗号分隔。同时我们应该知道的是枚举类型可以像类(class)类型一样,定义为一个单独的文件,当然也可以定义在其他类内部,更重要的是枚举常量在类型安全性和便捷性都很有保证,如果出现类型问题编译器也会提示我们改进,但务必记住枚举表示的类型其取值是必须有限的,也就是说每个值都是可以枚举出来的,比如上述描述的一周共有七天。

同时枚举也给我们提供了更多的方法操作所定义对象;

以上面性别枚举类举例;

//获取枚举对象的序号,序号从0开始System.out.println(Sex.MALE.ordinal());System.out.println(Sex.FEMALE.ordinal());// 把枚举对象转为字符串System.out.println(Sex.MALE.name());// 把字符串转为枚举对象, 虚拟机中的枚举对象只会有一份, 可以用== 来比较System.out.println(Sex.valueOf("MALE") == Sex.MALE);// 打印所有的枚举对象for (Sex value : Sex.values()) {System.out.println(value);}

设计模式

定义:编程中的一些套路,让我们的代码实现特定的目的,结构上更加优秀;

单例模式

单例模式(Singleton Pattern)

定义:虚拟机中这个类只有一个实例(一个对象);

特点:

1、单例类只能有一个实例。

2、单例类必须自己创建自己的唯一实例。

3、单例类必须给所有其他对象提供这一实例。

单例顾名思义,就只能有一个实例;因此它需要私有,然后自己去创建出这一个唯一实例;同时它又不是说就只能自己使用,它还需要给所有其他对象提供这个实例,供他们使用,因此简单单例的代码就有了大致模板;

public class Singleton1 {/*** 让构造方法私有,别人就没法创建此类的实例了*/private Singleton1() {}/*** 自己创建这个实例*/private static final Singleton1 ME = new Singleton1();/*** 获取唯一实例*/public static Singleton1 getInstance() {return ME;}}

上面我们就看出来,我们先创建了私有的构造方法,然后自行和创建他的实例;最后给一个公有方法返回我们创造的对象实例;供其他对象调用;

但是我们想一下,这种方法在一开始就创建出了唯一的单例了,可是如果我们很久不用呢?这种方法就叫饿汉式的单例模式,就不管别人用不用,在一开始就创建好实例;这种方法就不太好;

所以我们也可以在真正需要实例的时候再创建;这种方式叫懒汉式单例

但是懒汉式单例就会出现一个问题,即如果在多线程的环境下,就不一定能保证单例;

比如上面的例子如果我们的实例方法这样写

public class Singleton1 {private Singleton1() {}private static final Singleton1 ME = new Singleton1();public static Singleton2 getInstance() {if (ME == null) {ME = new Singleton2();}return ME;}

在我们还没有创建好 ME = new Singleton2();时,又新进来的线程判断ME还时null,这时他就会再创建一个实例;这就不是单例了,所以我们必须加锁;

普通方法加锁,就需要声明加锁的synchronized关键字;

public static synchronized Singleton2 getInstance() {// 当一次调用时ME == null为真, 当后续调用时ME == null为假,就不会执行创建对象的操作了if (ME == null) {ME = new Singleton2();}return ME;}

这样就保证了单例;

同时懒汉式的单例也有更好的实现方式;我们可以用静态内部类的方式,在我们调用方法的时候才实现单例的创建;

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

这里我们用一个测试类看看静态内部类的单例创建效果;

public class TestSingle {public static void main(String[] args) {Singleton4.test();System.out.println("========================");Singleton4.getInstance();Singleton4.getInstance();Singleton4.getInstance();}}

从上面的结果我们就能看出来,在没有调用获取单例的方法时,单例并没有被创建,holder拥有创建单例的功能,那部分的代码也没有执行,在我们调用后,先用houlder,执行了它的静态内部类,创建出了唯一单例;这就是懒汉模式单例的更优方式;

享元模式

享元模式是提倡重用已有的对象,而不是创建新的对象。

在Integer的valueOf方法中就用到了享元模式。

public static Integer valueOf(int i) {if (i >= IntegerCache.low && i <= IntegerCache.high)return IntegerCache.cache[i + (-IntegerCache.low)];return new Integer(i);}

这段代码是指如果数字在一个范围内则会返回一个存储在cache数组中的对象。即实现了对象的重复利用。

原型模式 prototype

原型模式(Prototype Pattern)是用于创建重复的对象,同时又能保证性能。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

根据已有对象来创建新的对象, 克隆;

使用场景,当对象属性很多,希望新的对象的大部分属性从原有对象复制而来。

public class User implements Cloneable {private String name;private int age;private Date birthday; public Date getBirthday() {return birthday;}public void setBirthday(Date birthday) {this.birthday = birthday;}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;}@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}}

浅拷贝和深拷贝

刚才的Cloneable实现的是浅拷贝,也就是说,对象的属性仅仅是复制了地址,没有把内容新复制一份

深拷贝是指所有的内容都得是全新的。

使用序列化流来进行深拷贝

protected Object clone() throws CloneNotSupportedException {//内存操作流ByteArrayOutputStream os = new ByteArrayOutputStream();try {// 把自己(当前对象)写入输出流new ObjectOutputStream(os).writeObject(this);// 拿到字节数组byte[] bytes = os.toByteArray();// 内存操作流ByteArrayInputStream is = new ByteArrayInputStream(bytes);// 对象输入流ObjectInputStream ois = new ObjectInputStream(is);return ois.readObject();} catch (IOException e) {e.printStackTrace();} catch (ClassNotFoundException e) {e.printStackTrace();}return null;}

建造器模式(Builder)

通过建造起模式可以使创建对象时调用构造方法更加灵活。

适用于有多个可省参数的构造方法。

例如有一个Person类,他有以下的属性

String sex 性别

String name 名字

Integer weight; 体重

Integer height; 身高

在调用构造方法时,所有属性都是可选的。如果使用一般的模式编写,则需要为所有可能都写一个构造方法。

如果改用建造器模式,代码量就会变得简单。

public class Person {private String name;private String sex;private Integer weight;private Integer height;@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", sex='" + sex + '\'' +", weight=" + weight +", 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);}}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;}}public class TestBuilder {// new Person.PersonBuilder() 0 170 "张三" "男"public static void main(String[] args) {Person person = new Person.PersonBuilder().sex("男").name("张三").height(170).build();System.out.println(person);}}

使用构造器可以让调用构造方法变得简单。

迭代器模式(iterator)

提供顺序访问聚合对象元素的方法,并且不暴露其底层表现;

定义:以一种一致的对集合内的元素进行遍历,而不用在乎集合内的数据结构

ArrayList 数组

LinkedList 链表

HashSet 数组+链表

TreeSet 二叉搜索树-》红黑树

for(Object o : 集合)

Iterator iter = 集合.iterator();

while(iter.hasNext()) {

iter.next();

}

策略模式 (Strategy)

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

java 集合或数组的排序算法

Collections.sort

Arrays.sort

基本类型 双基点快速排序

对象类型 TimSort (早期使用归并排序)

规模小 插入排序

把排序的规则抽取出来,形成比较器接口(Comparator),不同比较器的实现就称为策略

open close 开闭原则

算法不能改-- 体现的是close原则

比较器可以改 – 体现的是open原则

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);

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。