关于后端:面试官小伙子够了够了一个工厂模式你都在这说半个小时了

5次阅读

共计 4096 个字符,预计需要花费 11 分钟才能阅读完成。

前言

创立型模式、次要用于 解决 Java 对象的创立问题

工厂模式

工厂模式的阐明

在面向对象的编程中, 继承和多态的概念实现了 父类与子类之间的 (is-A) 关系

基于这种关系实现了子类的多态性, 这种形象的形式为子类提供了雷同的操作并且反对子类的功能性拓展。然而呈现了这样的问题?

Verhicle verhicle = new Car();

Verhicle verhicle = new Truck();

problem 所在

  1. 子类复写了父类的办法,那么子类实例化父类对象时,就必须每一个子类都要进行。这样就造成了对于不同的子类要调用不同的结构器去实例化父类对象。不足统一性操作
  2. 另外从下面的两行代码能够看出子类与父类之间的依赖关系、耦合度高
  3. 违反了 父类的开闭准则 子类的繁多职责准则

简略工厂模式的引入,实现逻辑的封装,应用公共的工厂类实现对立创建对象实例化父类的行为。

简略工厂模式

  • 简略工厂实现的三种形式

    1. 动态工厂模式
    2. 应用反射机制进行类注册
    3. 应用 newInstance 办法进行类注册

简略工厂的 UML 图

  • 动态工厂模式的解决形式

创立一个独自的 verhicle 简略工厂类。通过内置枚举贮存所有须要创立实例的子类,并通过对立的 create(type) 办法 依据传入参数的类型实现按需创立实例。

public class VerhicleFactory {
    public enum VerhicleType {Car,Truck,Boat;}

    public static Verhicle create(VerhicleType type) {if(type.equals(VerhicleType.Car)) {return new Car();
        }
        if(type.equals(VerhicleType.Truck)) {return new Truck();
        }
        if(type.equals(VerhicleType.Boat)) {return new Boat();
        }
        else return null;
    }
}

劣势

这种额定应用工厂类的形式,解决了上体面类实例化父类的毁坏繁多职责准则、实现了结构实例的统一性操作。

毛病

能够从存储的枚举看出,一旦新增拓展的子类就必须批改工厂的枚举,毁坏了工厂类本身的开闭准则。

依然没有解决父类的对内敞开的对外拓展的开闭准则。

  • 应用反射机制进行类注册的解决形式

为了解决动态工厂模式毁坏本身开闭准则的弊病、咱们能够应用反射机制使得注册的新类在应用时被实例化。从而保障了对外拓展开发,对内批改闭合。也就是说即便新增对父类拓展的子类,也不再从新批改动态工厂内的枚举。

// 服务端

public class Product {/* 类体内容 */}
public class Product1 extends Product {}
/*... 更多的拓展子类...*/
public class MoreProducts extends Product {}

/* 应用反射机制进行类注册的简略工厂模式 */

private Map<String,Class> registeredProduct = new 
    HashMap<String,Class>();

/** 实现对拓展子类的注册、所有的拓展子类将会被记录在 Map 汇合中
 *@parameter
 * productId 子类 ID 也就是子类的类型,对应动态工厂的枚举类型
 * productClass 子类的类对象,也就是子类的 Class 对象
 */
public void registerProduct(String productId, Class productClass) {registeredProduct.put(productId, productClass);
}

/** 更具传入的子类类型、结构对应的子类实例并返回
 *@parameter
 * ProductType 子类类型和下面的子类 ID 统一,对应动态工厂的枚举类型
 */
public Product createProduct(String ProductType) throws InstantiationException,IllegalAccessException {Class productClass = registeredProduct.get(ProductType);
    return (Product) productClass.newInstance();}

// 客户端就根据相应的办法,进行类的注册和实例创立

长处

解决了动态工厂类毁坏开闭准则的弊病,把注册和创立实例离开实现注册的类在应用时才实例化。

毛病

反射机制影响了程序性能、应用多了的话,程序性能必定要低效很多。

  • 应用 newInstance 办法进行类注册的简略工厂模式

只是基于下面反射机制进行类注册的思维进行了一个 小的批改

  1. 防止应用反射机制、进步性能
  2. 如何实现呢?

    • Map 汇合中不在存储 Class 对象,而是曾经创立的子类实例
  • 基类中创立一个形象办法
  • 子类全副复写、办法体是创立子类对象

    • 这样就能够实现下面 Map 汇合存储的时曾经创立的子类实例
// 服务端

public abstract class Product {Product newInstance();
}
public class Product1 extends Product {}
/*... 更多的拓展子类...*/
public class MoreProducts extends Product {
    @override
    public  MoreProducts newInstance() {return new MoreProducts();
    }
}

/* 应用反射机制进行类注册的简略工厂模式 */

private Map<String,Product> registeredProduct = new 
    HashMap<String,Product>();

/** 实现对拓展子类的注册、所有的拓展子类将会被记录在 Map 汇合中
 *@parameter
 * productId 子类 ID 也就是子类的类型,对应动态工厂的枚举类型
 * productClass 子类的类对象,也就是子类的 Class 对象
 */
public void registerProduct(String productId, Product productType) {registeredProduct.put(productId, productType);
}

/** 更具传入的子类类型、结构对应的子类实例并返回
 *@parameter
 * ProductType 子类类型和下面的子类 ID 统一,对应动态工厂的枚举类型
 */
public Product createProduct(String ProductId) throws InstantiationException,IllegalAccessException {Product productType  = registeredProduct.get(ProductId);
    return (Product) productType.newInstance();}

// 客户端就根据相应的办法,进行类的注册和实例创立

长处

把基类之间划为抽象类,解决了父类的开闭准则和子类的繁多职责准则。反对了创建对象的统一性操作。

毛病

类之间的继承关系造成代码仍然耦合度高的问题。

依然存在未实现父类对内批改闭合的危险。

工厂办法模式

工厂办法模式的 UML 图

解决形式:

  1. 服务端把产品接口化、对于所有须要拓展的产品能够间接实现对立接口办法,以及自定义办法。
  2. 另外抽象化工厂、能够将产品的服务化性能集成在形象工厂,并且内置结构实例的形象办法。那么所有的拓展产品的工厂类都能够继承实现对应的构造方法和性能。
//  sever
public interface Product{void features();      // 定义对立的性能
}
public class Product1 implements Product {/* 实现对立接口办法、以及自定义办法 */}
public class MoreProducts implements Product {/* 实现对立接口办法、以及自定义办法 */}

/* 工厂办法 */

public abstract class AbastractFactory {Product create();        // 定义对立结构器
    void sever(){/* 相应的对立服务性能 */}
}
public class Product1Factory implements AbstractFactory {/* 实现结构器 */}
public class MoreProductsFactory extends AbstractFactory {/* 实现结构器 */}

劣势:

将产品解耦,并且每一个拓展产品都有相应的工厂类实现对应的结构实例以及服务性能

毛病:

易造成工厂的冗余、拓展产品过多时呈现工厂类增多。

形象工厂模式

解决办法:

在工厂办法模式的根底之上、在形象工厂中不再独自创立对立的结构器,而是创立一类或者所有的拓展产品结构器。这样工厂类继承的时候只须要少了的继承就能够实现多个拓展产品的结构工作。

//  sever
public interface Product{void features();     // 定义对立的性能
}
public class Product1 implements Product {/* 实现对立接口办法、以及自定义办法 */}
public class MoreProducts implements Product {/* 实现对立接口办法、以及自定义办法 */}

/* 形象工厂模式 */

public abstract class AbastractFactory {Product createProduct1();        // 定义 Product1 结构器
    Product createMoreProducts();    // 定义 MoreProducts 结构器
    void sever(){/* 相应的对立服务性能 */}
}

public class ProductFactory extends AbstractFactory {/* 实现对应结构器 */}

长处:

缩小了工厂类的数量、防止冗余问题

最初

欢送关注公众号:前程有光,支付一线大厂 Java 面试题总结 + 各知识点学习思维导 + 一份 300 页 pdf 文档的 Java 外围知识点总结!

正文完
 0