GOF23-工厂模式
工厂方法模式是对简单工厂的一个衍生,解决了许多简单工厂模式的问题。首先完全实现‘开-闭 原则’,实现了可扩展。其次更复杂的层次结构,可以应用于产品结果复杂的场合。 说了这么多我们先来看看什么情况下使用工厂模式。
应用场景
第一种情况是对于某个产品,调用者清楚地知道应该使用哪个具体工厂服务,实例化该具体工厂,生产出具体的产品来。Java Collection中的iterator() 方法即属于这种情况。
第二种情况,只是需要一种产品,而不想知道也不需要知道究竟是哪个工厂为生产的,即最终选用哪个具体工厂的决定权在生产者一方,它们根据当前系统的情况来实例化一个具体的工厂返回给使用者,而这个决策过程这对于使用者来说是透明的。
工厂方法模式是在简单工厂模式的衍生,所以我们先来了解下什么是简单工厂。
一、简单工厂模式
1、首先先创建一个car的抽象类定义一个run方法
public interface Car {
public void run();
}
2、创建实现类 具体的两个产品
宝马车实现类
public class BMWCar implements Car {
public void run() {
System.out.println("bao ma car is running");
}
}
路虎车实现类
public class LandRoverCar implements Car {
public void run() {
System.out.println("LandRover car is runnning ");
}
}
3、创建汽车工厂
public class CarFactory {
public static Car createBMCar()
{
return new BMWCar();
}
public static Car createLandRoverCar()
{
return new LandRoverCar();
}
}
4、测试
public class Test {
public static void main(String[] args) {
Car car = CarFactory.createBMCar();
car.run();
}
}
测试结果 : bao ma car is running
总体来说,工厂模式适合:凡是出现了大量的产品需要创建,并且具有共同的接口时,可以通过工厂方法模式进行创建。但是同时简单工厂存在于这几个缺点。
缺点:
- 工厂类集中了所有实例(产品)的创建逻辑,一旦这个工厂不能正常工作,整个系统都会受到影响;
- 违背“开放 - 关闭原则”,一旦添加新产品就不得不修改工厂类的逻辑,这样就会造成工厂逻辑过于复杂
- 简单工厂模式由于使用了静态工厂方法,静态方法不能被继承和重写,会造成工厂角色无法形成基于继承的等级结构。
二、工厂方法模式
解决了什么问题
简单工厂模式存在着不易扩展,违背开闭原则的致命缺点。所以工厂方法就是在简单工厂的模式上解决它不易于扩展的缺点。
工厂方法的实现
- 首先先创建一个car的抽象类定义一个run方法
public interface Car {
public void run();
}
- 创建实现类 具体的两个产品
宝马车实现类
public class BMWCar implements Car {
public void run() {
System.out.println("bao ma car is running");
}
}
路虎车实现类
public class LandRoverCar implements Car {
public void run() {
System.out.println("LandRover car is runnning ");
}
}
- 抽象工厂
public interface CarFactory {
public Car createCar();
}
- 工厂实现类
宝马工厂
public class BMWCarFactory implements CarFactory {
public Car createCar() {
return new BMWCar();
}
}
路虎工厂
public class LandRoverCarFactory implements CarFactory {
public Car createCar() {
return new LandRoverCar();
}
}
- 测试
public class Consumer {
public static void main(String[] args) {
Car car1 = new BMWCarFactory().createCar();
Car car2 = new LandRoverCarFactory().createCar();
car1.run();
car2.run();
}
}
总结:
这里这样设计的好处,就是如果需要加新产品,只需要新增工厂实现类就行了,不需要去改原来的代码了。这就易于扩展,解决了简单工厂的缺点。缺点就是代码量也变多了。
三、抽象工厂模式
抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
在抽象工厂模式中,接口是负责创建一个相关对象的工厂,不需要显式指定它们的类。每个生成的工厂都能按照工厂模式提供对象。抽象工厂的源头是一个超级大厂,维护着若干个小厂。就算需求变了这边只需要改具体小厂的制作方法就行了。
1、产品类接口
手机类
public interface PhoneProducton {
void start();
void shutdown();
void call();
void sendMSS();
}
路由器类
public interface RouterProduction {
void start();
void shutdown();
void openWiFi();
}
2、具体品牌产品实现类
小米产品
//小米手机
public class XiaoMiPhone implements PhoneProducton {
@Override
public void start() {
System.out.println("小米手机开启");
}
@Override
public void shutdown() {
System.out.println("小米手机关闭");
}
@Override
public void call() {
System.out.println("小米手机打电话");
}
@Override
public void sendMSS() {
System.out.println("小米手机发短信");
}
}
//小米路由器
public class XiaoMiRouter implements RouterProduction{
@Override
public void start() {
System.out.println("小米路由器开启");
}
@Override
public void shutdown() {
System.out.println("小米路由器关闭");
}
@Override
public void openWiFi() {
System.out.println("小米WiFi开启");
}
}
华为产品
//华为手机
public class HuaWeiPhone implements PhoneProducton {
@Override
public void start() {
System.out.println("华为手机开启");
}
@Override
public void shutdown() {
System.out.println("华为手机关闭");
}
@Override
public void call() {
System.out.println("华为手机打电话");
}
@Override
public void sendMSS() {
System.out.println("华为手机发短信");
}
}
//华为路由器
public class HuaWeiRouter implements RouterProduction{
@Override
public void start() {
System.out.println("华为路由器开启");
}
@Override
public void shutdown() {
System.out.println("华为路由器关闭");
}
@Override
public void openWiFi() {
System.out.println("华为WiFi开启");
}
}
3、抽象工厂,生产抽象产品
public interface Factory {
//生产手机
PhoneProducton createPhone();
//生产路由器
RouterProduction createRouter();
}
4、具体品牌工厂实现类,生产各自品牌产品
小米工厂
public class XiaoMiFactory implements Factory{
@Override
public PhoneProducton createPhone() {
return new XiaoMiPhone();
}
@Override
public RouterProduction createRouter() {
return new XiaoMiRouter();
}
}
华为工厂
public class HuaWeiFactory implements Factory{
@Override
public PhoneProducton createPhone() {
return new HuaWeiPhone();
}
@Override
public RouterProduction createRouter() {
return new HuaWeiRouter();
}
}
5、消费者测试
public class Consumer {
public static void main(String[] args) {
System.out.println("---------小米产品----------");
PhoneProducton phone = new XiaoMiFactory().createPhone();
RouterProduction router = new XiaoMiFactory().createRouter();
phone.call();
router.openWiFi();
System.out.println("---------华为产品----------");
phone = new HuaWeiFactory().createPhone();
router = new HuaWeiFactory().createRouter();
phone.call();
router.openWiFi();
}
}
大概逻辑图
从代码可以看出,如果产品增加,我们就需要加实现类就行了。但是这样创建产品的过程就非常复杂了,需要增加很多代码。所以抽象工厂是真的工厂,工厂方法模式就相当于一条生产线。