设计模式(创建型)
软件设计模式(Design pattern),又称设计模式,是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性、程序的重用性。
工厂方法模式(Factory Method Pattern)
-
定义:它定义了一个用于创建对象的接口,但是让其子类决定将哪个类实例化。这使得一个类的实例化延迟到其子类。
public abstract class Fruit{ //水果抽象类 private final String name; public Fruit(String name){ this.name = name; } @Override public String toString(){ return name + "@" + hashCode(); //打印一下当前水果名称,还有对象的hashCode } }
-
将对象的创建封装到工厂中
public abstract class FruitFactory<T extends Fruit>{ //将水果工厂抽象为抽象类,添加泛型T由子类指定水果类型 public abstract T getFruit(); //不同的水果工厂,通过此方法生产不同的水果 }
public class AppleFactory extends FruitFactory<Apple>{ //苹果工厂,直接返回Apple,一步到位 @Override public Apple getFruit(){ return new Apple(); } }
public class Apple extends Fruit{ //苹果,继承自水果 public Apple(){ super("苹果"); } }
public class Orange extends Fruit{ //橘子,也继承自水果 public Orange(){ super("橘子"); } }
public class Main{ public static void main(String[] args){ test(new AppleFactory::getFruit); //比如现在要吃一个苹果,那么直接通过苹果工厂来获取苹果 } //此方法模拟吃掉一个水果 private static void test(Supplier<Fruit> supplier){ System.out.println(suppiler.get() + "被吃掉了,真好吃!"); } }
抽象工厂模式(Abstract Factory Pattern)
-
定义:它提供了一种将一组相关或相互依赖的对象创建的接口,而无需指定它们具体的类
public class Router{}
public class Table{}
public class Phone{}
public abtract class AbstractFactory{ public abstract Phone getPhone(); public abstract Table getTable(); public abstract Router getRouter(); }
建造者模式(Builder Pattern)
-
定义:它将对象的构建过程与其表示分离开来,使得同样的构建过程可以创建不同的表示
public class Student{ //student的属性 //一律使用建造者来创建,不对外直接开放 private Student(int id,int age,int grade,String name,String college,String profession,List<String> awards){ //初始化属性 } public static StudentBuilder builder(){ //通过builder方法直接获取建造者 return new StudentBuilder(); } public static class StudentBuilder{ //这里就直接创建一个内部类 //Builder也需要将所有的参数都进行暂时保存,所有Student怎么定义的这里就怎么定义 int id; int age; int grade; String name; String college; String profession; List<String> awards; public StudentBuilder id(int id){ //直接调用建造者对应的方法,为对应的属性赋值 this.id = id; return this; //为了支持链式调用,这里直接返回建造者本身,下同 } public StudentBuilder age(int age){ this.age = age; return this; } ... public StudentBuilder awards(String... awards){ this.awards = Arrays.asList(awards); return this; } public Student build(){ //最后只需要调用建造者提供的build方法即可根据配置返回一个对象 return new Student(id,age,grade,name,college,profession,awards); } } }
-
使用建造者来生成对象:
public static void main(String[] args){ Student student = student.builder() //获取建造者 .id(1) //逐步配置各个参数 .age(18) .grade(3) .name("小明") .awards("ICPC-ACM 区域赛 金牌","LPL 2022春季赛 冠军") .build(); //最后直接建造想要的对象 }
单例模式(Singleton Pattern)
-
定义:它确保一个类只有一个实例,并提供一个全局访问点来访问这个唯一实例。
-
使用场景:线程池和数据库链接的时候会使用到单例模式
-
饿汉式和懒汉式的相同点和不同点
-
相同点:
-
私有的构造函数
-
对外曝光一个方法进行提供对应的实例
-
-
不同点:
-
饿汉式:在属性上进行实例化对象,于是在类上,类构建的时候就会进行实例化
-
懒汉式:在使用的时候进行实例化当前的对象
-
-
-
饿汉式
public class Singleton{ //必须进行创建这个实例 private final static Singleton SINGLETON = new Singleton(); //必须要有的私有的构造函数。防止直接new对象 private Singleton(){} //向对外提供一个实例,如需要使用该实例对象,则是必须要通过此方法 public static Singleton getSingleton(){ return SINGLETON; } }
public class MainTest{ public static void main(String[] args){ Singleton s = Singleton.getSingleton(); Singleton s1 = Singleton.getSingleton(); System.out.println(s == s1); //true } }
-
懒汉式(线程安全)
public class Singleton{ //必须进行创建这个实例,volatile保证instance在线程之间的可见性 private volatile static Singleton instance; //必须要有的私有的构造函数。防止直接new对象 private Singleton(){} //向对外提供一个实例,如需要使用该实例对象,则是必须要通过此方法 //lock锁 public static Singleton getSingleton(){ //进行创建对象 if(instance == null){ //双重检查锁定 synchronized(Singleton.class){ if(instance == null){ Singleton singleton = new Singleton(); instance = singleton; } } } return instance; } }
原型模式(Prototype Pattern)
-
定义:使用原型实例指定待创建对象的类型,并且通过复制这个原型来创建新的对象
-
浅拷贝:对于类中基本数据类型,会直接赋值值给拷贝对象;对于引用类型,只会对复制对象的地址,而实际上指向的还是原来的那个对象
public static void main(String[] args){ int a = 10; int b = a; //基本类型浅拷贝 System.out.println(a == b); Object o = new Object(); Object k = o; //引用类型浅拷贝,拷贝的仅仅是对象上面对象的引用 System.out.println(o == k); }
-
深拷贝:无论是基本类型还是引用类型,深拷贝会将引用类型的所有内容,全部拷贝为一个新的对象,包括对象内部的所有成员变量,也会进行拷贝
public class Student implements Cloneable{ String name; public Student(String name){ this.name = name; } public String getName(){ return name; } @Override public Object clone() throws CloneNotSupportedException{ //改进一下,针对成员变量也进行拷贝 Student student = (Student) super.clone(); student.name = new String(name); return student; //拷贝完成后,再返回 } }
public static void main(String[] args) throws CloneNotSupportedException{ Student student = new Student("小明"); Student student1 = (Student)student.clone(); System.out.println(student.getName() == student1.getName()); }