1、先说说面向对象的基本原则:(简单复习复习,以前学得都忘得七七八八)

-  OCP(开闭原则,Open-Closed Principle): 一个软件的实体应当对扩展开放,对修改关闭。

-  DIP(依赖倒转原则,Dependence Inversion Principle): 要针对接口编程,不要针对实现编程。

-  LoD(迪米特法则,Law of Demeter):只与你直接的朋友通信,而避免与陌生人进行通信。(即类与类之间的关系尽量少)


2、工厂模式:

a、核心本质:

-  实例化对象,用工厂方法代替 new 操作。

-  将选择实现类,创建对象统一管理和控制。从而将调用者跟我们的实现类解耦。

b、详细的分类:

-  简单工厂模式:用来生产统一等级结构中的任意产品。(对于增加新的产品,需要修改已有的代码)

-  工厂方法模式:用来生产统一等级结构中的固定产品。(支持增加任意产品)

-  抽象工厂模式:用来生产不同产品族的全部产品。(对于增加新的产品,无能为力,支持增加产品族)


3、简单工厂模式:

-  简单工厂模式也叫做静态工厂模式,就是工厂类一般是使用静态方法,通过接收的参数的不同来返回不同的对象实例。

-  对于增加新产品,如果不能够修改代码,是无法扩展的。


-  简单的代码演示:

a、首先先创建一个接口和三个类,其中包含一个名为 Client01.java 的测试类,以及其类图的关系:

package com.geeklicreed.singlefactory;

public interface Car {
	void run();
}


package com.geeklicreed.singlefactory;

public class Byd implements Car{

	@Override
	public void run() {
		System.out.println("比亚迪在跑!");
	}
	
}
package com.geeklicreed.singlefactory;

public class Audi implements Car{

	@Override
	public void run() {
		System.out.println("奥迪在跑");
	}

}
package com.geeklicreed.singlefactory;

public class Client01 {
	public static void main(String[] args) {
		Audi audi = new Audi();
		Byd byd = new Byd();
		
		audi.run();
		byd.run();
		
		/*
		 	输出结果为:
		 	奥迪在跑
			比亚迪在跑!
		 */
	}
}

设计模式之工厂模式_第1张图片

-  注:我们可以看到,调用者 client 与 实现者 Byd 和 Audi 紧密耦合,调用者不仅需要知道其 Car 接口,还要清楚其 Car 接口下实现的所有的实现类。(就像我们原始社会一样,什么样的事情都得自己做,啥事都得知道,会活活把人累死的。)


b、在所在包中创建一个简单的汽车生产工厂 SingleCarFactory,它代替我们生产汽车:

package com.geeklicreed.singlefactory;

public class SingleCarFactory {
	public static Car createCar(String carType){
		if(carType == "奥迪"){
			return new Audi();
		}else if(carType == "比亚迪"){
			return new Byd();
		}else {
			return null;
		}
	}
}
package com.geeklicreed.singlefactory;

public class Client {
	public static void main(String[] args) {
		Byd byd = (Byd) SingleCarFactory.createCar("比亚迪");
		Audi audi = (Audi) SingleCarFactory.createCar("奥迪");
		
		byd.run();
		audi.run();
		
		/*输出结果为:
		比亚迪在跑!
		奥迪在跑*/
	}
}

设计模式之工厂模式_第2张图片

-  注:可以看到,调用者 Client02 只和 SingleCarFactory 与接口 Car 耦合,不与实际的实现类打交道。


4、工厂方法模式:

-  为了避免简单工厂模式的缺点,即不完全满足 OCP(开闭原则)

-  工厂方法模式和简单工厂模式最大的不同在于,简单工厂模式只有一个(对于一个项目或者一个独立模块而言)工厂类,而工厂方法模式有一组实现了相同接口的工厂类。


-  简单代码演示:

a、和简单工厂一样,一个 Car 接口和 Byd 和 Audi 的实现类,此外再加上一个 CarFactory 接口 和 BydFactory 实现类和 AudiFactory 实现类。

package com.geeklicreed.singlefactory;

public interface Car {
	void run();
}
package com.geeklicreed.singlefactory;

public class Audi implements Car{

	@Override
	public void run() {
		System.out.println("奥迪在跑");
	}

}
package com.geeklicreed.singlefactory;

public class Byd implements Car{

	@Override
	public void run() {
		System.out.println("比亚迪在跑!");
	}
	
}
package com.geeklicreed.singlefactory;

public interface CarFactory {
	Car createFactory();
}
package com.geeklicreed.singlefactory;

public class AudiFactory implements CarFactory{

	@Override
	public Car createFactory() {
		return new Audi();
	}

}
package com.geeklicreed.singlefactory;

public class BydFactory implements CarFactory{

	@Override
	public Car createFactory() {
		return new Byd();
	}

}


b、在 Client03 的这个测试类中填写代码,以及工厂方法模式的示例的类图

package com.geeklicreed.singlefactory;

public class Client {
	public static void main(String[] args) {
		Car car1 = new AudiFactory().createFactory();
		Car car2 = new BydFactory().createFactory();
		
		car1.run();
		car2.run();
		
		/*输出结果为:
		奥迪在跑
		比亚迪在跑!*/
	}
}

设计模式之工厂模式_第3张图片

-  注:我们可以看到,工厂方法模式中,调用者 Client03 只需要和 CarFactory 与 AudiFactory 以及 BydFactory 耦合,与其他类并没有关系。


5、抽象工厂模式:

-  用来生产不同产品族的全部产品。(对于增加新的产品,无能为力;支持增加产品族)

-  抽象工厂模式是工厂方法模式的升级版,在有多个业务品种、业务分类时,通过抽象工厂模式产生需要的对象是一种非常好的解决方式。

   

-  简单的代码演示:

a、创建 Engine、Seat 和 Type 接口,以及其对应的实现类 LuxuryEngine 和 LowEngine,LuxurySeat 和 LowSeat,LuxuryType 和 LowType 。

package com.geeklicreed.abstractfactory;

public interface Engine {
	void start();
	void run();
}

class LuxuryEngine implements Engine{
	public void start(){
		System.out.println("启动块!");
	}
	public void run(){
		System.out.println("耗油量少");
	}
}

class LowEngine implements Engine{
	public void start(){
		System.out.println("启动慢!");
	}

	public void run() {
		System.out.println("耗油量多");
	}
}
package com.geeklicreed.abstractfactory;

public interface Type {
	void abrase();
}

class LuxuryType implements Type{
	public void abrase(){
		System.out.println("行驶不磨损!");
	}
}

class LowType implements Type{
	public void abrase(){
		System.out.println("行驶磨损,不耐用!");
	}
}
package com.geeklicreed.abstractfactory;

public interface Seat {
	void comfort();
}

class LuxurySeat implements Seat {
	@Override
	public void comfort() {
		System.out.println("坐得舒服");
	}
}

class LowSeat implements Seat {
	@Override
	public void comfort() {
		System.out.println("坐得感觉还行吧");
	}
}


b、创建 CarFactory 接口,以及其对应的实现类 LowCarFactory 和 LuxuryCarFactory 。

package com.geeklicreed.abstractfactory;

public interface CarFactory {
	Engine createEngine();
	Seat createSeat();
	Type createType();
}
package com.geeklicreed.abstractfactory;

public class LowCarFactory implements CarFactory{

	@Override
	public Engine createEngine() {
		return new LowEngine();
	}

	@Override
	public Seat createSeat() {
		return new LowSeat();
	}

	@Override
	public Type createType() {
		return new LowType();
	}
	
}

c、创建 Client04 测试类,这个抽象工厂的示例的类图如下所示。

package com.geeklicreed.abstractfactory;

public class Client {
	public static void main(String[] args) {
		CarFactory carFactory = new LowCarFactory();
		Engine engine = carFactory.createEngine();
		Seat seat = carFactory.createSeat();
		engine.start();
		engine.run();
		seat.comfort();

		/*输出结果为:
		启动慢!
		耗油量多
		坐得感觉还行吧*/
	}
}

设计模式之工厂模式_第4张图片


-  注:可以看到,client04 调用者只与 CarFactory 接口和其实现类 LuxuryCarFactory 和 LowCarFactory 相耦合。


6、简单工厂模式和工厂方法模式PK:

-  结构复杂度:简单工厂模式占优。简单工厂模式只需要一个工厂类,而工厂方法模式的工厂类随着产品的增加而增加,增加了类结构的复杂度。

-  代码复杂度:代码复杂度和结构复杂度是一对矛盾。既然简单工厂模式在结构方面相对简洁,那么他在代码方面肯定比工厂方法模式复杂的多。

-  客户端编程难度:工厂方法模式虽然在工厂类结构中引入接口从而满足 OCP,但是在客户端编码中需要对类进行实例化,而简单工厂模式的工厂类是个静态类,在客户端无需实例化,这无疑是一个吸引人的优点。

-  扩展性:工厂方法模式完全满足 OCP 原则,具备很好的扩展性,而简单工厂模式扩展性不足。

-  所以,综合上面的情况,根据设计理论建议:工厂方法模式。但是我们在实际开发中,一般会选择使用简单工厂模式。


7、应用场景:

- JDK 中 Calenda 的 getInstance方法。

- JDBC 中 Connection 对象的获取。

- Hibernate 中 SessionFactory 创建 Session。

- spring 中 IOC 容器创建管理 bean 对象。