设计模式
编程中的一些套路,让我们的代码实现特定的目的,是结构上更加高效
单例模式
虚拟机中的这个类只有一个实例(一个对象)
实现方法
1.饿汉式单例模式
先定义静态实例
public class Singleton1 {
//将构造方法私有
private Singleton1(){
}
//创建单例
private static final Singleton1 ME = new Singleton1();
//得到单例对象
public static Singleton1 getMe(){
return ME;
}
}
测试一下
public class TestSingle {
public static void main(String[] args) {
//构造方法私有不能通过构造创建
Singleton1 s1 = Singleton1.getMe();
Singleton1 s2 = Singleton1.getMe();
//比较两个对象的地址值
System.out.println(s1==s2);
}
}
2.懒汉式单例模式
先定义引用
public class Singleton2 {
private Singleton2(){
}
//仅仅只创建引用
private static Singleton2 ME;
//再多线程环境下,有可能会创建出多个单例
//因此需要同步
public static synchronized Singleton2 getME(){
if(ME==null){
ME = new Singleton2();
}
return ME;
}
}
测试一下
public class TestSingle {
public static void main(String[] args) {
Singleton2 s1 = Singleton2.getME();
Singleton2 s2 = Singleton2.getME();
//比较地址值
System.out.println(s1==s2);
}
}
3.枚举实现单例模式
通过枚举特性实现,也算是饿汉式单例
public enum Singleton3{
ME;
}
4.静态内部类改善后的懒汉式单例
public class Singleton4 {
static {
System.out.println(" Singleton4");
}
private Singleton4(){
}
//创建唯一实例
private static class Holder{
static {
System.out.println(" Singleton4 Holder");
}
static Singleton4 ME = new Singleton4();
}
public static Singleton4 getME(){
return Holder.ME;
}
static{
System.out.println("Singleton4 getME");
}
}
破坏单例
1.反射可以调用似有构造(不能阻止)
2.反序列化可以破坏单例(可以阻止 大家可以自己去看)
享元模式(FlyWeight)
提倡重用已有的对象,而不是创建新的对象。
比如Interger中的valueOf()方法
/* public static Integer valueOf(int i) {
* if (i >= IntegerCache.low && i <= IntegerCache.high)
* return IntegerCache.cache[i + (-IntegerCache.low)];
* return new Integer(i);
* }
*/
享元范围 -127 - 128
原型模式 prototype
根据已有的对象来创建新的对象,克隆
适合当对象属性很多,希望新对象的属性和已有对象的属性相同的情况
实现方法
public class User implements Cloneable{
private String name;
private int age;
public User() {
}
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
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
测试代码
public class Test {
public static void main(String[] args) throws CloneNotSupportedException {
User user = new User();
user.setAge(18);
user.setName("Mike");
User user1 = (User)user.clone();
System.out.println(user == user1);
System.out.println(user1.getAge() + user1.getName());
}
}
深拷贝和浅拷贝
1.使用Cloneable实现的是浅拷贝,只是复制了地址,里面的内容并不是全新的
2.通过序列化和反序列化流实现
import java.io.*;
import java.util.Date;
public class User2 implements Cloneable, Serializable {
private String name;
private int age; // 18 --> 18
private Date birthday; // #1234 --> #1234
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;
}
@Override
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;
}
}
建造器模式
让你给我们创建对象更加灵活,适用于一步一步构建一个较为复杂的对象
实现方法
public class Person {
private String name;
private String sex;
private Integer weight;
private Integer height;
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", sex='" + sex + '\'' +
", weight=" + weight +
", height=" + 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);
}
}
public String getName() {
return name;
}
public String getSex() {
return sex;
}
public Integer getWeight() {
return weight;
}
public Integer getHeight() {
return height;
}
}
public class Test{
public static void main(String[] args){
Person person = new Person.PersonBulider()
.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();
}
策略模式
策略模式是对算法的包装,是把使用算法本身分割开来,委派给不同的对象管理。
实现方法
比如在Java中的集合或者数组排序算法(分为3种情况)
1.基本类型 双基点快速排序
2.引用类型 TimeSort(早期使用归并排序)
3.规模小 插入排序
排序的的算法是固定的,但是排序的规则不是固定的。我们可以通过比较器来实现不同的排序规则。
我们将不同的比较器接口的实现就称为排序策略(体现了open-close原则)。