创建型设计模式共5种,分别为工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
一、工厂方法模式
工厂方法模式指定义一个用于创建对象的接口,让子类决定实例化哪一个类。使一个类的实例化延迟到其子类。
在工厂方法模式中存在四种角色,分别为抽象工厂,具体工厂,抽象产品,具体产品。具体工厂及具体产品是对抽象工厂及抽象产品的实现。使用抽象工厂可以对业务进行解耦,提升灵活性,屏蔽工厂内产品细节,但每增加一种产品都需要增加对应的具体产品及具体工厂,代码复用性较差。以车举例,代码demo如下
创建抽象产品BaseCar及具体产品FourRoundsCar、ThreeRoundsCar
public interface BaseCar {
void run ();
}
public class FourRoundsCar implements BaseCar {
@Override
public void run() {
System.out.println("四轮车");
}
}
public class ThreeRoundsCar implements BaseCar {
@Override
public void run() {
System.out.println("三轮车");
}
}
创建抽象工厂BaseCarFactory及具体工厂FourRoundsCarFactory、ThreeRoundsCarFactory
public interface BaseCarFactory {
public BaseCar getCar();
}
// 各工厂负责实例化不同类
public class FourRoundsCarFactory implements BaseCarFactory {
@Override
public BaseCar getCar() {
return new FourRoundsCar();
}
}
public class ThreeRoundsCarFactory implements BaseCarFactory {
@Override
public BaseCar getCar() {
return new ThreeRoundsCar();
}
}
创建测试类进行调用
public class Test {
public static void main(String[] args) {
ThreeRoundsCarFactory threeRoundsCarFactory = new ThreeRoundsCarFactory();
BaseCar threeRoundsCar = threeRoundsCarFactory.getCar();
threeRoundsCar.run();
FourRoundsCarFactory fourRoundsCarFactory = new FourRoundsCarFactory();
BaseCar fourRoundsCar = fourRoundsCarFactory.getCar();
fourRoundsCar.run();
}
}
二、抽象工厂模式
抽象工厂模式是工厂方法模式的升级版本,它用来创建一组相关或者相互依赖的对象。其与工厂方法模式的区别在于,工厂方法模式针对的是一个产品等级结构;而抽象工厂模式则是针对的多个产品等级结构(产品族)。使用抽象工厂模式可以对产品族进行约束,但如果要新增一个产品则需要改动所有工厂类,以车为例,代码demo如下:
定义奥迪车的两款产品三轮车,四轮车并实现其定义
public interface FourRoundsCar {
void createFourRounds();
}
public interface ThreeRoundsCar {
void createThreeRounds();
}
public class AudiFourRoundsCar implements FourRoundsCar{
@Override
public void createFourRounds() {
System.out.println("创建奥迪四轮车");
}
}
public class AudiThreeRoundsCar implements ThreeRoundsCar {
@Override
public void createThreeRounds() {
System.out.println("创建奥迪三轮车");
}
}
创建抽象工厂
public interface BaseCarFactory {
FourRoundsCar getFourRoundsCar();
ThreeRoundsCar getThreeRoundsCar();
}
创建奥迪工厂
public class AudiCarFactory implements BaseCarFactory {
@Override
public FourRoundsCar getFourRoundsCar() {
return new AudiFourRoundsCar();
}
@Override
public ThreeRoundsCar getThreeRoundsCar() {
return new AudiThreeRoundsCar();
}
}
创建测试类
public class Test {
public static void main(String[] args) {
BaseCarFactory factory = new AudiCarFactory();
FourRoundsCar fourRoundsCar = factory.getFourRoundsCar();
fourRoundsCar.createFourRounds();
ThreeRoundsCar threeRoundsCar = factory.getThreeRoundsCar();
threeRoundsCar.createThreeRounds();
}
}
三、单例模式
单例模式指内存中只会存在一个对象,而且自行实例化并向整个应用系统提供这个实例。常见单例模式使用懒汉式、饿汉式、枚举实现。
懒汉式:需要时加载,避免资源浪费,但第一次加载时较慢。
public class Singleton {
private static Singleton instance;
// 避免外部实例化
private Singleton() {
}
public static Singleton getInstance() {
// 双重检查保证线程安全
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
饿汉式:初始化时创建实例,但浪费空间。
public class Singleton {
private static Singleton instance = new Singleton();
// 避免外部实例化
private Singleton() {
}
public static Singleton getInstance() {
return instance;
}
}
枚举创建:使用枚举创建单例可以避免反射暴力破解和序列化带来的问题,并且枚举是线程安全的。
新建要实例化的实体Singleton
public class Singleton {
}
新建枚举InstanceEnum
public enum InstanceEnum {
SINGLETON;
private Singleton singleton;
private InstanceEnum() {
singleton = new Singleton();
}
public Singleton getInstance() {
return singleton;
}
}
使用时直接InstanceEnum.SINGLETON.getInstance();调用即可
四、建造者模式
建造者模式存在四种角色分别为指挥者、抽象建造者、具体建造者、具体产品。其与工厂模式区别在于多了一个指挥者,通过指挥者封装复杂调用逻辑。使用建造者模式可以屏蔽建造者内具体实现逻辑,通过调用不同建造者可获取同一产品的不同实现。但建造者模式不适用于内部变化复杂的产品,如果产品的内部变化复杂,需要定义很多具体建造者类来实现复杂变化,如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统臃肿。以车的创建为例,demo如下
创建产品car
public class Car {
private String name;
private String tire;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getTire() {
return tire;
}
public void setTire(String tire) {
this.tire = tire;
}
}
创建抽象建造者Builder
public interface Builder {
void createName();
void createTrie();
/**
* 获取产品
* @return
*/
Car getCar();
}
创建具体建造者FourRoundsBuilder与ThreeRoundsBuilder
public class FourRoundsBuilder implements Builder {
private Car car = new Car();
@Override
public void createName() {
car.setName("四轮车");
}
@Override
public void createTrie() {
car.setTire("四个轮胎");
}
@Override
public Car getCar() {
return car;
}
}
public class ThreeRoundsBuilder implements Builder {
private Car car = new Car();
@Override
public void createName() {
car.setName("三轮车");
}
@Override
public void createTrie() {
car.setTire("三个轮胎");
}
@Override
public Car getCar() {
return car;
}
}
创建指挥者Director
public class Director {
public static Car builder(Builder builder) {
builder.createName();
builder.createTrie();
return builder.getCar();
}
}
创建调用类Test
public class Test {
public static void main(String[] args) {
FourRoundsBuilder fourRoundsBuilder = new FourRoundsBuilder();
Car fourRoundsCar = Director.builder(fourRoundsBuilder);
System.out.println(fourRoundsCar.getTire());
ThreeRoundsBuilder threeRoundsBuilder = new ThreeRoundsBuilder();
Car threeRoundsCar = Director.builder(threeRoundsBuilder);
System.out.println(threeRoundsCar.getTire());
}
}
五、原型模式
原型模式指用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的新对象。使用原型方式创建对象非常高效并无须知道对象创建的细节。
原型模式实现方式主要为深拷贝与浅拷贝。
浅拷贝demo如下,对应类需要实现Cloneable接口
public class Car implements Cloneable {
private String name;
private String tire;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getTire() {
return tire;
}
public void setTire(String tire) {
this.tire = tire;
}
@Override
public String toString() {
return "name:" + name + ",tire:" + tire;
}
@Override
public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
}
创建测试类
public class Test {
public static void main(String[] args) {
Car car = new Car();
car.setName("三轮车");
car.setTire("三个轮胎");
Car newCar = (Car) car.clone();
System.out.println(newCar.toString());
}
}
深拷贝分为两种,第一种在每个类中进行克隆,代码如下,新建car类在克隆时对引擎engine进行克隆car.setEngine((Engine) car.getEngine().clone());
public class Car implements Cloneable {
private String name;
private String tire;
private Engine engine;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getTire() {
return tire;
}
public void setTire(String tire) {
this.tire = tire;
}
public Engine getEngine() {
return engine;
}
public void setEngine(Engine engine) {
this.engine = engine;
}
@Override
public String toString() {
return "name:" + name + ",tire:" + tire;
}
@Override
public Object clone() {
try {
Car car = (Car) super.clone();
car.setEngine((Engine) car.getEngine().clone());
return car;
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
}
public class Engine implements Cloneable {
private String engineName;
public String getEngineName() {
return engineName;
}
public void setEngineName(String engineName) {
this.engineName = engineName;
}
@Override
public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
@Override
public String toString() {
return "engineName:" + engineName;
}
}
第二种使用序列化进行克隆
public interface Prototype {
/**
* 获取深拷贝对象
* @param prototype
* @return
*/
Prototype getDeepClone(Prototype prototype);
}
public class Car implements Serializable,Prototype {
private static final long serialVersionUID = 1L;
private String name;
private String tire;
private Engine engine;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getTire() {
return tire;
}
public void setTire(String tire) {
this.tire = tire;
}
public Engine getEngine() {
return engine;
}
public void setEngine(Engine engine) {
this.engine = engine;
}
@Override
public String toString() {
return "name:" + name + ",tire:" + tire;
}
@Override
public Prototype getDeepClone(Prototype prototype) {
return CloneUtil.getSerializInstance(prototype);
}
}
public class Engine implements Serializable,Prototype {
private static final long serialVersionUID = 1L;
private String engineName;
public String getEngineName() {
return engineName;
}
public void setEngineName(String engineName) {
this.engineName = engineName;
}
@Override
public String toString() {
return "engineName:" + engineName;
}
@Override
public Prototype getDeepClone(Prototype prototype) {
return CloneUtil.getSerializInstance(prototype);
}
}
public class CloneUtil {
/**
* 通过序列化深拷贝
* @param prototype
* @return
*/
public static Prototype getSerializInstance(Prototype prototype){
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(prototype);
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
Prototype copy = (Prototype)ois.readObject();
bos.flush();
bos.close();
ois.close();
return copy;
}catch (Exception e){
e.printStackTrace();
}
return null;
}
}