工厂模式
作用:
实现了创建者与调用者的分离
详细分类
简单工厂模式
工厂方法模式
抽象工厂模式
OOP七大原则:
开闭原则:一个软件的实体应该对拓展开发,对修改关闭
依赖反转原则:要针对接口编程,不要针对实现编程
迪米特原则:只与你的朋友通信,避免与陌生人通信
核心本质:
实例化对象不使用new,用工厂方式替代
将选择实现类,创建对象统一管理和控制,从而将调用者跟我们的实现类解耦
三种模式:
简单工厂模式(静态工厂模式)
用来生产同一等级结构中的任意产品(对于增加新的产品,需要覆盖已有代码)
工厂方法模式
用来生产同一等级结构的固定产品(支持赠加任意产品)
抽象工厂模式
围绕一个超级工厂创建其他工厂,该超级工厂又被称为其他工厂的工厂
简单工厂模式:
我们最开始的new一个对象,就相当于我们自己制造一个新的事物一样, 对象的创建与本身业务逻辑联系精密,如下图所示:
简单工厂模式的核心是定义一个创建对象的接口,将对象的创建和本身的业务逻辑分离,降低系统的耦合度,使得两个修改起来相对容易些,当以后实现改变时,只需要修改工厂类即可。
如下图示:
代码展示:
产品接口
public interface Car {
void name();
}
工厂:
public class CarFactory {
public static Car getCar(String car){
if (car.equals("五菱")){
return new wuling();
}else if(car.equals("特斯拉")){
return new Tesla();
}else{
return null;
}
}
}
产品实现类
public class Tesla implements Car{
public void name() {
System.out.println("特斯拉");
}
}
public class wuling implements Car{
@Override
public void name() {
System.out.println("五菱宏光");
}
优点:
简单工厂模式提供专门的工厂类用于帮助客户端创建对象,实现了对象创建和使用的职责分离,客户端不需知道所创建的具体产品类的类名以及创建过程,只需知道具体产品类所对应的参数即可,通过引入配置文件,可以在不修改任何客户端代码的情况下更换和增加新的具体产品类,在一定程度上提高了系统的灵活性。
缺点:
但缺点在于不符合“开闭原则”,每次添加新产品就需要修改工厂类。在产品类型较多时,有可能造成工厂逻辑过于复杂,不利于系统的扩展维护,并且工厂类集中了所有产品创建逻辑,一旦不能正常工作,整个系统都要受到影响。
为了解决简单工厂模式的问题,出现了工厂方法模式。
工厂方法模式:
代码展示:
产品接口
public interface Car {
void name();
}
工厂接口
public interface CarFactory {
Car getCar(String car);
}
产品实现类及工厂实现类
public class tesla implements Car{
public void name() {
System.out.println("特斯拉");
}
}
public class wulin implements Car{
@Override
public void name() {
System.out.println("五菱宏光");
}
}
public class teslaFactory implements CarFactory{
@Override
public Car getCar(String car) {
return new tesla();
}
}
public class wulinFactory implements CarFactory{
@Override
public Car getCar(String car) {
return new wulin();
}
}
客户端
public class Consumer {
public static void main(String[] args) {
Car car = new wulinFactory().getCar("五菱");
car.name();
Car car1 = new teslaFactory().getCar("特斯拉");
car1.name();
}
}
工厂方法模式创建了产品接口与工厂接口,每增加一个新的产品,只需要增加该产品的实现类,以及该工厂的实现类,由具体的工厂类来决定实例化哪个产品。将对象的创建与实例化延迟到子类,这样工厂的设计就符合“开闭原则”了,扩展时不必去修改原来的代码。而在客户端使用时,只需要知道对应的工厂即可,其他的都不需要知道,实现了系统的解耦,
缺点:
每新增一个产品都需要新增一个产品实现类和一个工厂实现类,一定程度上增加了系统代码的复杂性
简单工厂模式与工厂方法模式的对比:
结构复杂度:简单工厂模式更好
代码复杂度:简单工厂模式
编程复杂度:简单工厂
管理上的复杂度:简单工厂
根据设计原则:我们应该使用工厂方法模式
但根据实际业务:我们大多数时候使用的都是简单工厂模式
小结:
简单工厂模式(静态工厂模式)
虽然某种程度上不符合设计原则,但实际使用最多
工厂方法模式
不修改已有类的前提下,通过增加新的工厂实现扩展
抽象工厂模式
不可以增加产品,可以增加产品族
应用场景:
JDK中Calendar的getInstance方法
JDBC中的Connection对象的获取
Spring中IOC容器创建管理bean对象
反射中Calss对象的newInstance方法
抽象工厂模式
定义:抽象工厂模式提供了一个创建一系列相关或者相互依赖的接口,无需指定他们具体的类
实用场景:
客户端(应用层)不依赖产品实例如何被创建,实现等细节
强调一系列相关的产品对象(属于同一产品族)一起使用创建对象需要大量的重复代码
提供一个产品类的库,所有的产品以同样的接口出现,从而使得客户端不依赖于具体的实现
产品等级:就类似于手机生产中不同的厂商生产的不同品牌的手机,但功能大致相同
产品族:就类似于一个厂商推出的一系列的电子商品
UML类图
代码展示:
产品接口类:
抽象工厂接口(重点):
public interface ProductFactory {
//生产手机
PhoneProduct phoneproduct();
// 生产路由器
RouterProduct routerproduct();
}
public interface PhoneProduct {
void start();
void shutdown();
void call();
void send();
}
public interface RouterProduct {
void start();
void shutdown();
void openWifi();
void setting();
}
手机产品工厂实现类
package com.lyc.FactoryDemo.abstract1;
public class xiaomiPhone implements PhoneProduct{
@Override
public void start() {
System.out.println("小米手机开机");
}
@Override
public void shutdown() {
System.out.println("小米手机关机");
}
@Override
public void call() {
System.out.println("小米手机打电话");
}
@Override
public void send() {
System.out.println("小米手机发短信");
}
}
package com.lyc.FactoryDemo.abstract1;
public class HUaweiPhone implements PhoneProduct{
@Override
public void start() {
System.out.println("华为手机开机");
}
@Override
public void shutdown() {
System.out.println("华为手机关机");
}
@Override
public void call() {
System.out.println("华为手机打电话");
}
@Override
public void send() {
System.out.println("华为手机发短信");
}
}
路由器产品工厂实现类
package com.lyc.FactoryDemo.abstract1;
public class XiaomiRouter implements RouterProduct{
@Override
public void start() {
System.out.println("小米路由器开机");
}
@Override
public void shutdown() {
System.out.println("小米路由器关机");
}
@Override
public void openWifi() {
System.out.println("小米路由器打开wifi");
}
@Override
public void setting() {
System.out.println("小米路由器设置");
}
}
package com.lyc.FactoryDemo.abstract1;
public class HuaweiRouter implements RouterProduct{
@Override
public void start() {
System.out.println("华为路由器开机");
}
@Override
public void shutdown() {
System.out.println("华为路由器关机");
}
@Override
public void openWifi() {
System.out.println("华为路由器打开wifi");
}
@Override
public void setting() {
System.out.println("华为路由器设置");
}
}
产品族工厂实现类
package com.lyc.FactoryDemo.abstract1;
public class XiaomiFactory implements ProductFactory{
@Override
public PhoneProduct phoneproduct() {
return new xiaomiPhone();
}
@Override
public RouterProduct routerproduct() {
return new XiaomiRouter();
}
}
package com.lyc.FactoryDemo.abstract1;
public class HuaweiFactory implements ProductFactory{
@Override
public PhoneProduct phoneproduct() {
return new HUaweiPhone();
}
@Override
public RouterProduct routerproduct() {
return new HuaweiRouter();
}
}
客户端
package com.lyc.FactoryDemo.abstract1;
public class Client {
public static void main(String[] args) {
System.out.println("======小米系列产品=====");
PhoneProduct phoneproduct = new XiaomiFactory().phoneproduct();
phoneproduct.start();
phoneproduct.shutdown();
RouterProduct routerproduct = new XiaomiFactory().routerproduct();
routerproduct.start();
routerproduct.shutdown();
routerproduct.openWifi();
System.out.println("======华为系列产品=====");
PhoneProduct phoneproduct1 = new HuaweiFactory().phoneproduct();
phoneproduct1.start();
phoneproduct1.shutdown();
RouterProduct routerproduct1 = new HuaweiFactory().routerproduct();
routerproduct1.start();
routerproduct1.shutdown();
routerproduct1.openWifi();
}
}
开发中客户端直接访问产品族工厂再进行产品制造就可以了,其余的也并不需要知道了,
具体类图
抽象工厂模式主要用于创建相关对象的家族。当一个产品族中需要被设计在一起工作时,通过抽象工厂模式,能够保证客户端始终只使用同一个产品族中的对象;并且通过隔离具体类的生成,使得客户端不需要明确指定具体生成类;所有的具体工厂都实现了抽象工厂中定义的公共接口,因此只需要改变具体工厂的实例,就可以在某种程度上改变整个软件系统的行为。
优点:
具体产品在应用层的代码隔离,无需关心创建的细节
将一个系列的产品统一到一起创建
缺点:
规定了所有可能被创建的产品集合,产品族中扩展的产品较困难
增加了系统的抽象性与理解难度
抽象工厂只负责定义,设置接口或者说规范,子共产按照规范来实现
抽象工厂模式,聚焦于产品族(品牌)上,适合产品等级(类别)较固定的一些场景
抽象工厂较为晦涩难懂,建议自己在重新编写代码,建立类图,在进行理解!