大聪明教你学Java设计模式 | 第三篇:工厂模式

578 阅读9分钟

前言

这是我参与2022首次更文挑战的第5天,活动详情查看:2022首次更文挑战

大聪明在写代码的过程中发现设计模式的影子是无处不在,设计模式也是软件开发人员在软件开发过程中面临的一般问题的解决方案。大聪明本着“独乐乐不如众乐乐”的宗旨与大家分享一下设计模式的学习心得。

咱们书接上文~ 在上一篇博客中,大聪明为大家讲解了一下建造者模式,那么建造者模式和工厂模式又有什么关系呢?二者之间有什么异同呢?下面请听大聪明为大家娓娓道来~

1.工厂模式

工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。 在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。

工厂模式又可以分成简单工厂模式、工厂方法模式、抽象工厂模式。

  • 简单工厂模式:用来生产同一等级结构中的任意产品。(对于增加新的产品,需要修改已有代码)
  • 工厂方法模式:用来生产同一等级结构中的固定产品。(支持增加任意产品)
  • 抽象工厂模式:用来生产不同产品族的全部产品。(对于增加新的产品,无能为力;支持增加产品族)

这么说还是有点抽象,下面大聪明就为大家一一介绍。

(1)简单工厂模式

①定义接口

public interface Car {
	void run();
}

②实现类

public class Aodi implements Car {
	@Override
	public void run() {
		System.out.println("奥迪呜呜跑...");
	}
}
public class Byd implements Car {
	@Override
	public void run() {
		System.out.println("比亚迪呜呜跑!");
	}
}

③简单工厂类

public class CarFactory {
	public static  Car createCar(String type){
		if("奥迪".equals(type)){
			return new Aodi();
		}else if("比亚迪".equals(type)){
			return new Byd();
		}else{
			return null;
		}
	}
}

public class CarFactory2 {
	
	public static  Car createAudi(){
		return new Aodi();
	}
	public static  Car createByd(){
		return new Byd();
	}
}

④测试类

public class test {
	public static void main(String[] args) {
		Car c1 =CarFactory.createCar("奥迪");
		Car c2 = CarFactory.createCar("比亚迪");
		c1.run();
		c2.run();
	}
}

通过上面的代码大家可以看出简单工厂模式(静态工厂模式)工厂类一般是使用静态方法,通过接收的参数的不同来返回不同的对象实例。不过缺点也是显而易见的,简单工厂模式对于增加新产品是无能为力的,如果不修改代码,是无法扩展的。

(2)工厂方法模式

①定义业务接口

public interface Car {
	void run();
}

②接口实现类

public class Aodi implements Car {
	@Override
	public void run() {
		System.out.println("奥迪呜呜跑!");
	}
}
public class BenChi implements Car {
	@Override
	public void run() {
		System.out.println("奔驰呜呜跑!");
	}
}

③定义工厂接口

public interface Car {
	void run();
}

④为每个car实现类对应创建一个工厂类

public class AodiFactory implements CarFactory {
	@Override
	public Car createCar() {
		return new Aodi();
	}
}
public class BenChiFactory implements CarFactory {
	@Override
	public Car createCar() {
		return new BenChi();
	}
}

⑤测试类

public class Client {
	public static void main(String[] args) {
		Car c1 = new AodiFactory().createCar();
		Car c2 = new BenChiFactory().createCar();
		c1.run();
		c2.run();
	}
}

大家从示例中可以看到,工厂方法模式避免了简单工厂模式的缺点。它和简单工厂模式最大的不同在于,简单工厂模式只有一个工厂类,而工厂方法模式有一组实现了相同接口的工厂类。

这时候大聪明有了一个疑问:那么这二者到底哪个更好呢?我们在开发的过程中到底应该使用哪种模式呢?

从结构复杂度和代码复杂度的角度来说,我们一眼就可以看出简单工厂模式在结构复杂度上是低于工厂方法模式的,但是这也就意味着简单工厂模式的代码复杂度会高于工厂方法模式(简单工厂模式的工厂类随着产品类的增加需要增加很多方法,而工厂方法模式每个具体工厂类只完成单一任务,代码会更简洁一些)。

那么咱们再从管理角度和代码编写的角度来分析二者的查别。

工厂方法模式完全满足开闭原则,这就意味着它有非常良好的扩展性。这是否就说明了简单工厂模式就没有扩展性呢?答案当然是否定的。简单工厂模式在扩展的时候仅需要修改少量的代码(修改工 厂类的代码)就可以满足扩展性的要求了。尽管这没有完全满足开闭原则,但我们不需要太过拘泥于设计理论(毕竟java官方工具包中也有很多没有满足开闭原则的代码)。 假如某个具体产品类需要进行一定的修改,很可能需要修改对应的工厂类。假如我们此时使用的是工厂方法模式,当需要同时修改多个产品类的时候,那么对工厂类的修改会变得相当麻烦。反观简单工厂模式却没有这些麻烦,当多个产品类需要修改的时候,仅仅需要修改唯一的工厂类就可以了。

所以我们在根据设计理论考虑问题时无疑是选择工厂方法模式。但实际上,我们在使用的过程中一般都用简单工厂模式。

大聪明:说白了就是理想很丰满,现实很骨感~

(3)抽象工厂模式

①产品类

//发动机以及型号  
public interface Engine {  
 
}  
public class EngineA implements Engine{  
    public EngineA(){  
        System.out.println("制造-->EngineA");  
    }  
}  
public class EngineB implements Engine{  
    public EngineB(){  
        System.out.println("制造-->EngineB");  
    }  
}  
 
//空调以及型号  
public interface Aircondition {  
 
}  
public class AirconditionA implements Aircondition{  
    public AirconditionA(){  
        System.out.println("制造-->AirconditionA");  
    }  
}  
public class AirconditionB implements Aircondition{  
    public AirconditionB(){  
        System.out.println("制造-->AirconditionB");  
    }  
} 

②工厂类

//创建工厂的接口  
public interface AbstractFactory {  
    //制造发动机
    public Engine createEngine();
    //制造空调 
    public Aircondition createAircondition(); 
}  
 
 
//为宝马X3系列生产配件  
public class FactoryBMWX3 implements AbstractFactory{  
    @Override  
    public Engine createEngine() {    
        return new EngineA();  
    }  
    @Override  
    public Aircondition createAircondition() {  
        return new AirconditionA();  
    }  
}  
//宝马X6系列
public class FactoryBMWX6 implements AbstractFactory {  
     @Override  
    public Engine createEngine() {    
        return new EngineB();  
    }  
    @Override  
    public Aircondition createAircondition() {  
        return new AirconditionB();  
    }  
} 

③测试类

public class Customer {  
    public static void main(String[] args){  
        //生产宝马X3系列配件
        FactoryBMWX3 factoryBMWX3 = new FactoryBMWX3();  
        factoryBMWX3.createEngine();
        factoryBMWX3.createAircondition();
          
        //生产宝马X6系列配件  
        FactoryBMWX6 factoryBMWX6 = new FactoryBMWX6();  
        factoryBMWX6.createEngine();
        factoryBMWX6.createAircondition();
    }  
}

抽象工厂模式是工厂方法模式的升级版本,在有多个业务品种、业务分类时,通过抽象工厂模式产生需要的对象是一种非常好的解决方式。 它与工厂方法模式的区别就在于,工厂方法模式针对的是一个产品等级结构;而抽象工厂模式则是针对的多个产品等级结构。在编码过程中,通常一个产品结构,表现为一个接口或者抽象类,也就是说,工厂方法模式提供的所有产品都是衍生自同一个接口或抽象类,而抽象工厂模式所提供的产品则是衍生自不同的接口或抽象类。 在抽象工厂模式中,有一个产品族的概念:所谓产品族,是指位于不同产品等级结构中功能相关联的产品组成的家族。抽象工厂模式所提供的一系列产品就组成一个产品族;而工厂方法提供的一系列产品称为一个等级结构。

大聪明:你说NM呢?说的通俗点!!!

咱们用个更通俗的例子来帮大家更好的理解产品族和等级结构,还拿车来举个例子:两厢车和三厢车称为两个不同的等级结构;而2.0排量车和2.4排量车则称为两个不同的产品族。再具体一点,2.0排量两厢车和2.4排量两厢车属于同一个等级结构,2.0排量三厢车和2.4排量三厢车属于另一个等级结构;而2.0排量两厢车和2.0排量三厢车属于同一个产品族,2.4排量两厢车和2.4排量三厢车属于另一个产品族。 在这里插入图片描述 明白了等级结构和产品族的概念,就可以更好的理解工厂方法模式和抽象工厂模式的区别了,如果工厂的产品全部属于同一个等级结构,则属于工厂方法模式;如果工厂的产品来自多个等级结构,则属于抽象工厂模式。

小结

最后再总结一下工厂模式和建造者模式的区别:工厂模式一般都是创建一个产品,注重的是把这个产品创建出来就行,不关心这个产品的组成部分到底是什么;而建造者模式不仅仅是要把这个产品创建出来,还需要关心它的创建过程和组成的细节,这也是二者最明显的区别。 无论是简单工厂模式,工厂方法模式,还是抽象工厂模式,他们都属于工厂模式,在形式和特点上也是极为相似的,他们的最终目的都是为了解耦。在使用时,我们不必去纠结这个模式到底工厂方法模式还是抽象工厂模式,因为他们之间的演变常常是令人琢磨不透的。所以,在使用工厂模式时只需要关系是否解耦了就好。

本人经验有限,有些地方可能讲的没有特别到位,如果您在阅读的时候想到了什么问题,欢迎在评论区留言,我们后续再一一探讨🙇‍

希望各位小伙伴动动自己可爱的小手,来一波点赞+关注 (✿◡‿◡) 让更多小伙伴看到这篇文章~ 蟹蟹呦(●'◡'●)

如果文章中有错误,欢迎大家留言指正;若您有更好、更独到的理解,欢迎您在留言区留下您的宝贵想法。

爱你所爱 行你所行 听从你心 无问东西