工厂设计模式 抽象工厂 1.抽象工厂使用场景 2.原则 3.使用案例 4.JDK源码分析

使用端要不断创建某类对象,并且这类对象可以细分为不同种类。此时可以使用抽象工厂,其细分的种类由不同工厂创建。

2.原则

  1. 使用端依赖抽象
  2. 已经使用的类不再修改,扩展可以添加新的工厂

3.使用案例

需求:
肠粉店有许多功能相同的客户端,需要根据肠粉下单名称,创建肠粉订单对象。
肠粉可以分为广州口味,北京口味等的肠粉类型。
根据抽象工厂设计模式类图如下。

3.1类图

工厂设计模式 抽象工厂
1.抽象工厂使用场景
2.原则
3.使用案例
4.JDK源码分析

3.2代码

abstract class CF {
	public void prepare();
	public void cook() {
		System.out.println("蒸肠粉");
	}
	public void oil() {
		System.out.println("淋上肠粉酱油");	
	}
	public void box() {
		System.out.println("打包发货");
	}
}

class BJEggCf extends CF {
	public void prepare() {
		System.out.println("准备北京口味的鸡蛋肠粉");
	}
}
class GZEggCF extends CF {
	public void prepare() {
		System.out.println("准备广州口味的鸡蛋肠粉");
	}
}

interface AbsFactory {
	public CF createCF(String type);
}

class BJFactory implements AbsFactory {
	public CF createCF(String type) {
		if(type == "egg") {
			return new BJEggCF();
		}
	}
}

class GZFactory implements AbsFactory {
	public CF createCF(String type) {
		if(type == "egg") {
			return new GZEggCF();
		}
	}
}

//CF对象使用端
class Client1 {
	AbsFactory absFactory;
	public void setFactory(AbsFactory absFactory) {
		this.absFactory = absFactory;
	}

	//返回客户下单的类型
	String getType() {
		return "egg";
	}

	public void createOrder() {
		CF order = this,absFactory.createCF(this.getType);
	}
}

class Client2 {
	AbsFactory absFactory;
	public void setFactory(AbsFactory absFactory) {
		this.absFactory = absFactory;
	}

	//返回客户下单的类型
	String getType() {
		return "egg";
	}

	public void createOrder() {
		CF order = this,absFactory.createCF(this.getType);
	}
}

4.JDK源码分析

在JDK的Calender类中,就使用了工厂模式创建Calandar对象。

 Calendar a = Calendar.getInstance();
public static Calendar getInstance()
    {
        return createCalendar(TimeZone.getDefault(), Locale.getDefault(Locale.Category.FORMAT));
    }
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 no known calendar type is explicitly specified,
            // perform the traditional way to create a Calendar:
            // create a BuddhistCalendar for th_TH locale,
            // a JapaneseImperialCalendar for ja_JP_JP locale, or
            // a GregorianCalendar for any other locales.
            // NOTE: The language, country and variant strings are interned.
            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;
    }