创建型设计模式

        创建型设计模式共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;
	    }
}


版权声明:本文为shaofei_huai原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。