Java工厂模式详解

发布时间:2023年12月27日

1.概念

工厂模式是一种创建型模式(什么是创建型模式,见我发布的单例模式详解文章,或者狗子们自己百度下),它提供了一种创建对象的最佳方式。在此模式下,我们使用工厂类创建对象,而非使用new关键字实例化对象。

工厂模式的主要目的是将对象的创建与使用分离,使代码更加灵活和可维护。它通过将对象的创建委托给工厂类来实现,工厂类根据不同的条件或参数来决定创建哪种类型的对象。

2.要素

工厂模式通常包含以下几个角色:

  1. 抽象产品(Product):定义了产品的接口,所有具体产品都必须实现这个接口。
  2. 具体产品(Concrete Product):实现了抽象产品接口的具体类。
  3. 抽象工厂(Abstract Factory):定义了创建产品的接口,包含一个或多个创建产品的方法。
  4. 具体工厂(Concrete Factory):实现了抽象工厂接口,负责创建具体产品的对象。

3.举例

下面是一个工厂模式常见的经典例子:

其实每次定义代码结构之前,要先抽象需求,这个慢慢要培养。

首先我们定义一个产品的抽象接口。

复习下

Java接口也是抽象的,为什么?因为接口没有具体的实现,其实没有具体实现的都可以看做是抽象的。抽象对应具体,是不是又学到了。

车是抽象的(不要抬杠,我们认为只有具体车型的车是具体的),定义个抽象的车的接口,接口定义一个驾驶方法,

比如分自动挡和手动挡的驾驶,但是不管怎样,车肯定都要能驾驶(家庭开支之后,我特喵现在连个车都买不起,狗子们多努力)

// 抽象产品
interface Car
{
    void drive();
}

定义手动挡实现类

class SdCar implements Car {
    @Override
    public void drive() {
        System.out.println("手动挡驾驶");
    }
}

定义自动挡实现类

class ZdCar implements Car {
    @Override
    public void drive() {
        System.out.println("自动挡驾驶");
    }
}

这个时候我们不要new直接创建实例化对象,采用工厂方法:

定义一个创建车对象的接口方法,现在懵逼不要急

// 抽象工厂
interface  CarFactory {
    Car CreateCar();
}

我们再分别创建自动挡和手动挡车的实现类,都是工厂概念

class ZdCarFactory implements CarFactory {
    @Override
    public Car CreateCar() {
        return new ZdCar();
    }
}

class SdCarFactory implements CarFactory {
    @Override
    public Car CreateCar() {
        return new SdCar();
    }
}

我们看怎么使用上面,也就是以客户端的代码:

// 客户端代码
public class Main {
    public static void main(String[] args) {
         //工厂级别
         CarFactory sd_factory=new SdCarFactory();
        //具体的车级别实例
         Car sd_car=sd_factory.CreateCar();
         sd_car.drive()

         //工厂级别
         CarFactory zd_factory=new ZdCarFactory();
        //具体的车级别实例
         Car zd_car=zd_factory.CreateCar();
         zd_car.drive()
    }
}

有些人到客户端就看不懂了,我来给狗子们复习下下面知识。

接口是不能被实例化的,也就是说接口不能使用new创建实例化对象,为什么?因为接口是抽象的,new是实例化之后具体的。

但是接口可以指向实现类的对象,也叫向上造型(upcasting)。向上造型是安全的,因为接口是实现类的抽象,可以保证实现类实现了接口中定义的所有方法。这种其实就叫“多态性”。

对应的向下造型(downcasting)是将一个父类对象转换为子类对象的过程。在Java中,如果一个接口指向实现类的对象,然后将该接口转换为实现类类型,这被称为向下造型。向下造型是不安全的,因为接口可能没有实现类的特定方法或属性,这样的转换可能会导致运行时异常。因此,在进行向下造型时,应该先使用instanceof运算符进行类型检查,以确保对象的类型是正确的。向下造型一般用在继承当中,继承就不用复习了吧。

所以举一个案例:

Java向上造型

public interface Car {
void drive();
}

public class SDCar implements Car{

	@Override
	public void drive() {
		// TODO Auto-generated method stub
		System.out.println("手动挡驾驶");
	}

}

public class ZDCar implements Car{

	@Override
	public void drive() {
		// TODO Auto-generated method stub
		System.out.println("自动挡驾驶");
	}

}

客户端
public class Fatcory {
	
	public static void main(String[] args) {
        //接口指向了实现类的对象,肯定也实现了自己的方法,所以指向谁,调用
        //接口的方法,就是谁的
		Car car_zd =new ZDCar();
		car_zd.drive();
		//输出:自动挡驾驶
		Car car_sd =new SDCar();
		car_sd.drive();
		//输出:手动挡驾驶
	}

}

?Java向下造型:

class Animal {
    public void sound() {
        System.out.println("动物类声音");
    }
}

class Dog extends Animal {
    public void sound() {
        System.out.println("狗叫声,这个是子类重写父类的方法。。。。");
    }

    public void fetch() {
        System.out.println("狗狗抓东西,这个是子类自己的方法。。。");
    }
}

public class Main {
    public static void main(String[] args) {
        //父类子化,同接口,属于向上造型
        Animal animal = new Dog(); // 向上造型,继承也有向上造型
        animal.sound(); // 调用的是Dog类的sound方法


        //子类父亲化,但是东西全都是自己的,相当于名义上构造了一个对象实例,操作的都是自己的
        Dog dog = (Dog) animal; // 向下造型
        dog.sound(); // 调用的是Dog类的sound方法
        dog.fetch(); // 调用的是Dog类的fetch方法
    }
}

4.总结

首先千万不要把工厂方法理解为单个到批量,这么理解是不对的,其实你想想,程序员文学水平能有多高。

其实是两次分别的接口向上造型,其实完全一次接口向上造就可以将创建对象,但是不符合封装的概念了。

工厂-->生产--->不同品牌有自己的生产方式-->生产出来的车要符合车的抽象概念,车-->都要能驾驶-->

不同种类的车有不同的驾驶方式。

使用的时候也是从工厂级别开始:

工厂接口 具体的工厂实现类对象=new 具体的工厂实现类(一次向上造型)

具体的工厂实现类对象调用抽象方法创建各自的Car对象(一次向上造型)

各自的Car对象调用各自的驾驶方法

这个时候顺便理解下向上造型。

5.应用场景

应用场景包括:

  1. 对象的创建需要复杂的逻辑或条件判断:工厂模式可以将对象的创建逻辑封装在工厂类中,根据不同的条件返回不同的对象实例。
  2. 需要统一管理对象的创建:工厂模式可以将对象的创建集中在一个工厂类中,方便管理和维护。
  3. 需要隐藏对象的创建细节:工厂模式可以将对象的创建细节隐藏在工厂类中,对外只暴露一个简单的接口,降低了使用者的复杂度。
  4. 需要动态地切换对象的实现:工厂模式可以通过修改工厂类的实现,实现对不同对象实现的切换,而不需要修改使用者的代码。
  5. 需要扩展对象的创建:工厂模式可以通过添加新的工厂类或修改现有的工厂类,实现对新对象的创建,而不需要修改使用者的代码。

总之,工厂模式适用于需要灵活、可扩展、可维护的对象创建场景。

文章来源:https://blog.csdn.net/xiaomeng2013/article/details/135200969
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。