前言
工厂模式,是Java最常用的设计模式之一。属于创建型模式,提供创建对象的最佳方式。适用于创建复杂对象场景。如果是简单对象,比如new就可以的,如果使用工厂模式,就需要引入工厂类,反而增加了复杂度。
复杂对象:类的构造方法参数过多或构造过于复杂,在业务代码中直接引用耦合度较高。后续业务的更改带来的影响和依赖过大,修改地方过多,而工厂模式能很好的解决这些问题。
按照实际业务场景进行划分,工厂模式有3中不同的实现方式:简单工厂模式、工厂方法模式、抽象工厂模式。
简单工厂模式
又叫静态工厂方法模式,有一个具体的工厂类,只需要传入工厂类参数,不需要关心创建对象的逻辑,就可以很方便的创建所需产品。
例如:
public class Client {
public static void main(String[] args) {
new SimpleFactory().createProduct("B").print();
}
// 抽象产品
public interface Product {
void print();
}
// 具体产品A
public static class ProductA implements Product {
@Override
public void print() {
System.out.println("商品A");
}
}
// 具体产品B
public static class ProductB implements Product {
@Override
public void print() {
System.out.println("商品B");
}
}
// 简单工厂
public static class SimpleFactory {
/**
* 根据入参类型生成具体产品
*/
public static Product createProduct(String type) {
switch (type) {
case "A":
return new ProductA();
case "B":
return new ProductB();
}
return null;
}
}
}
?运行结果:
简单工厂模式在JDK中的应用
private static Calendar createCalendar(TimeZone zone,Locale aLocale)
{
CalendarProvider provider =
LocaleProviderAdapter.getAdapter(CalendarProvider.class, aLocale)
.getCalendarProvider();
if (provider != null) {
try {
return provider.getInstance(zone, aLocale);
} catch (IllegalArgumentException iae) {
// fall back to the default instantiation
}
}
Calendar cal = null;
if (aLocale.hasExtensions()) {
String caltype = aLocale.getUnicodeLocaleType("ca");
if (caltype != null) {
switch (caltype) {
case "buddhist":
cal = new BuddhistCalendar(zone, aLocale);
break;
case "japanese":
cal = new JapaneseImperialCalendar(zone, aLocale);
break;
case "gregory":
cal = new GregorianCalendar(zone, aLocale);
break;
}
}
}
if (cal == null) {
if (aLocale.getLanguage() == "th" && aLocale.getCountry() == "TH") {
cal = new BuddhistCalendar(zone, aLocale);
} else if (aLocale.getVariant() == "JP" && aLocale.getLanguage() == "ja"
&& aLocale.getCountry() == "JP") {
cal = new JapaneseImperialCalendar(zone, aLocale);
} else {
cal = new GregorianCalendar(zone, aLocale);
}
}
return cal;
}
优点:简单方便
缺点:工厂类单一,负责所有产品创建,产品种类增多后,switch ...case分支过多,工厂类将非常臃肿
工厂方法模式
又叫多态性工厂模式,主要解决产品扩展问题。不再是单一的工厂类生产产品,而是由工厂类的子类实现具体产品的创建,因此,当增加一个产品时,只需增加一个相应的工厂子类,避免了工厂类switch ...case分支过多导致的臃肿,符合开闭原则。
例如:
public class Client {
public static void main(String[] args) {
new FactoryA().createProduct().print();
new FactoryB().createProduct().print();
}
// 抽象产品
public interface Product {
void print();
}
// 具体产品A
public static class ProductA implements Product {
@Override
public void print() {
System.out.println("商品A");
}
}
// 具体产品B
public static class ProductB implements Product {
@Override
public void print() {
System.out.println("商品B");
}
}
// 抽象工厂
public interface Factory {
Product createProduct();
}
// 生产ProductA的具体工厂
public static class FactoryA implements Factory {
@Override
public Product createProduct() {
return new ProductA();
}
}
// 生产ProductB的具体工厂
public static class FactoryB implements Factory {
@Override
public Product createProduct() {
return new ProductB();
}
}
}
?运行结果:?
优点:灵活性增强,解耦。
缺点:具体工厂类的数量容易过多;抽象产品只能生产一种产品,此弊端可由抽象工厂模式解决。
抽象工厂模式
抽象工厂模式是工厂方法模式的扩展,在实际使用中,产品总是按照类型统一出现,而工厂方法模式中,一个子类工厂只能创建一种产品的方式比较鸡肋,我们往往需要一个工厂可以创建出一个类型的多种产品,同时也能降低子工厂类数量的增长速度。
例如:
public class Client {
public static void main(String[] args) {
new FactoryA().createProductA().printA();
new FactoryA().createProductB().printB();
}
// 抽象产品A
public interface ProductA {
void printA();
}
// 抽象产品B
public interface ProductB {
void printB();
}
// 产品族A的具体产品A
public static class ProductATypeA implements ProductA {
@Override
public void printA() {
System.out.println("苹果生态的ipad");
}
}
// 产品族A的具体产品B
public static class ProductBTypeA implements ProductB {
@Override
public void printB() {
System.out.println("苹果产品的macbook");
}
}
// 产品族B的具体产品A
public static class ProductATypeB implements ProductA {
@Override
public void printA() {
System.out.println("华为生态的matepad");
}
}
// 产品族B的具体产品B
public static class ProductBTypeB implements ProductB {
@Override
public void printB() {
System.out.println("华为生态的matebook");
}
}
// 抽象工厂
public interface Factory {
ProductA createProductA();
ProductB createProductB();
}
// 具体工厂A
public static class FactoryA implements Factory {
@Override
public ProductA createProductA() {
return new ProductATypeA();
}
@Override
public ProductB createProductB() {
return new ProductBTypeA();
}
}
// 具体工厂B
public static class FactoryB implements Factory {
@Override
public ProductA createProductA() {
return new ProductATypeB();
}
@Override
public ProductB createProductB() {
return new ProductBTypeB();
}
}
}
运行结果:
抽象工厂模式在Spring源码中的应用
Spring中,所有的工厂都是BeanFactory的子类,可以通过不同的策略调用getBean方法,获得不同的实例对象。
public interface BeanFactory {
Object getBean(String var1) throws BeansException;
<T> T getBean(String var1, Class<T> var2) throws BeansException;
Object getBean(String var1, Object... var2) throws BeansException;
<T> T getBean(Class<T> var1) throws BeansException;
<T> T getBean(Class<T> var1, Object... var2) throws BeansException;
}
优点:需要创建同一类型产品时,即产品族,无需单独创建额外的工厂
缺点:增加了理解难度和抽象性
|