工厂模式的实现
原文链接:java的三种工厂模式
前言
工厂顾名思义就是创建产品,根据产品是具体产品还是具体工厂可分为简单工厂模式和工厂方法模式,根据工厂的抽象程度可分为工厂方法模式和抽象工厂模式。该模式用于封装和管理对象的创建,是一种创建型模式。本文从一个具体的例子逐步深入分析,来体会三种工厂模式的应用场景和利弊。
通过工厂模式,将创建产品实例的权利移交工厂,我们不再通过new来创建我们所需的对象,而是通过工厂来获取我们需要的产品。降低了产品使用者与使用者之间的耦合关系
一、简单工厂
抽象的产品行为接口
public interface Vehicle {
void go();
}
具体的产品行为
public class Car implements Vehicle{
@Override
public void go() {
System.out.println("开车!!!!!!dududududu");
}
}
public class Plane implements Vehicle{
@Override
public void go() {
System.out.println("开飞机!!!!!tatatatata");
}
}
产品行为工厂类
public class VehicleFactory {
//简单工厂,提供获取具体对象的方法
public Car createCar(){
return new Car();
}
//静态工厂方法
public static Plane createPlane(){
return new Plane();
}
}
该工厂可以是一个纯静态方法的 多方法静态工厂(常用),
也可以创建一个 用于选择生产具体产品的工厂方法,根据不同的入参来确定创建哪种具体实列。
使用工厂获取实列
public class CustomerMain {
public static void main(String[] args) {
//创建 简单工厂的实列
VehicleFactory vehicleFactory = new VehicleFactory();
//开汽车
Car car = vehicleFactory.createCar();
car.go();
//开飞机
Plane plane = VehicleFactory.createPlane();
plane.go();
}
}
特点
1 它是一个具体的类,非接口 抽象类。有一个重要的create()方法,可以利用if或者 switch来判断创建具体产品实列并返回。
2 create()方法通常是静态的,所以也称之为静态工厂。
缺点
1 扩展性差(想要增加其它的交通工具行为模式,还需要修改工厂的方法)
2 不同的产品需要不同额外参数的时候 不支持。
二、工厂方法模式
厂方法模式是把普通工厂就是把简单工厂中具体的工厂类,划分成两层:抽象工厂层+具体的工厂子类层。
为了解决简单工厂的问题,程序员们又想出来一个新的办法,就是设计一个工厂的接口,你想要什么东西,就写个类继承于这个工厂,这样就不用修改什么,直接添加就行了。就相当于,我这个工厂是用来生产鞋子的,而要什么品牌的鞋子具体分到了每个车间,如果新多了一种品牌的鞋子,直接新增一个车间就行了。
第一一个生产交通工具的工厂接口
public interface VehicleFactory {
Vehicle makeVehicle();
}
具体生产那种交通工具的 具体生产工厂
汽车生产车间
public class CarFactory implements VehicleFactory{
@Override
public Car makeVehicle() {
return new Car();
}
}
飞机车间
public class PlaneFactory implements VehicleFactory{
@Override
public Plane makeVehicle() {
return new Plane();
}
}
抽象交通工具生产接口
public interface Vehicle {
void get();
}
具体交通员工具制造类
public class Car implements Vehicle {
@Override
public void get() {
System.out.println("轮子+底盘+骨架+外壳.......");
}
}
public class Plane implements Vehicle {
@Override
public void get() {
System.out.println("螺旋桨+外壳+发动机+雷达.....");
}
}
外界通过调用具体工厂类的方法,从而创建不同具体产品类的实例
public class CustomerMain {
public static void main(String[] args) {
//创建 工厂方法模式 实现实列
VehicleFactory carFactory = new CarFactory();
//制造汽车
//这里 实现了抽象工厂类的 CarFactory() 工厂 就相当于一个起床制造车间
//可以提供 足够的方法来 提供生产一辆汽车所需要的 零件
Car car = (Car)carFactory.makeVehicle();
car.get();
//制造飞机 的生产车间工厂
PlaneFactory planeFactory = new PlaneFactory();
Plane plane=(Plane) planeFactory.makeVehicle();
plane.get();
}
}
三、抽象工厂
1、介绍
意图:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
主要解决:主要解决接口选择的问题。
何时使用:系统的产品有多于一个的产品族,而系统只消费其中某一族的产品。
如何解决:在一个产品族里面,定义多个产品。每个具体的工厂负责一个产品族。抽象工厂的返回值为最高级抽象产品。
关键代码:在一个工厂里聚合多个同类产品(在同一个产品族中)。
应用实例:举一个衣服与衣柜的例子。家里边,有男装(产品族,其中包含休闲男装和商务男装)、女装(产品族,其中包含休闲女装和商务女装)。商务女装、商务男装、时尚女装、时尚男装,这些都是具体产品。男装专门放在男衣柜(具体工厂)中,女装专门放在女衣柜(具体工厂)中。当我们需要拿衣服时候,从衣柜(抽象工厂)中获取。
也就是说,我们可以通过超级工厂来获取一个 族工厂,列如获取一个 喵星人工厂,就可以知道喵星人的族工厂得知 其 爱好、行为、大小…
动物类
public abstract class Animal {
abstract void food();//食物
abstract void call();//叫声
abstract void height();//身高
}
喵星人一族
蓝猫
public class BlueCat extends Animal{
@Override
void food() {
System.out.println("喵星人 蓝猫 喜欢吃🐟");
}
@Override
void call() {
System.out.println("喵星人 蓝猫 喵喵喵的叫");
}
@Override
void height() {
System.out.println("喵星人 蓝猫 高 1.5cm");
}
}
加菲猫
public class GaffeyCat extends Animal{
@Override
void food() {
System.out.println("喵星人 加菲猫 喜欢吃🐟");
}
@Override
void call() {
System.out.println("喵星人 加菲猫 喵喵喵的叫");
}
@Override
void height() {
System.out.println("喵星人 加菲猫 高 1.5cm");
}
}
动物抽象工厂
public abstract class AnimalFactory {
abstract Animal getAnimal(String name);
}
喵星人具体实现工厂
public class CatsFactory extends AnimalFactory{
@Override
Animal getAnimal(String name) {
//通过类名,创建喵星人一族的具体成员
Class cl=null;
Object o=null;
try {
cl = Class.forName(name);
o = cl.newInstance();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
return (Animal) o;
}
}
超级工厂(获取指定的 动物工厂)
public class SuperFactory {
//获取指定的 动物族群工厂
//获取喵星人一族
public static AnimalFactory getCatsFactory(){
return new CatsFactory();
}
//获取汪星人一族
public static AnimalFactory getDogsFactory(){
return new DogsFactory();
}
}
具体实现演示
通过超级工厂获取喵星人一族的工厂,然后通过喵星人一族的 工厂,获取指定的喵星人。
public class Main {
public static void main(String[] args) {
//通过超级工厂 获取喵星人工厂
CatsFactory catsFactory = (CatsFactory)SuperFactory.getCatsFactory();
//通过喵星人工厂获取 蓝猫
BlueCat animal = (BlueCat)catsFactory.getAnimal("abstractFactory.BlueCat");
animal.food();
animal.call();
animal.height();
//通过喵星人工厂获取 加菲猫
GaffeyCat gaffeyCat = (GaffeyCat)catsFactory.getAnimal("abstractFactory.GaffeyCat");
gaffeyCat.food();
gaffeyCat.call();
gaffeyCat.height();
}
}
四、什么时候用接口,什么时候用抽象类
形容词使用接口,名词使用抽象类。
也就是说,接口是对一些统一的行为的规范;而抽象类可以是一些真实存在的物体的抽象。