设计模式---工厂模式

工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单使用的模式。简单工厂模式定义了一个创建对象的类,由这个类来封装实例化对象的行为。在软件开发中,当我们会用到大量的创建某种、某类或者某批量对象时,就会使用到工厂模式。

一、简单工厂模式案例


需求:用户可以通过一个披萨工厂类来获取自己想要的披萨。
工厂模式设计方案:首先将披萨项目的实例抽象成抽象方法,在不同的口味子类中具体实现。同时定义一个披萨的工厂类 (SimplePizzaFactory)来获取想要的披萨对象。它向工厂类中传递信息(GREEK 等),以便获取它所需要的对象类型。
类图通过类图,查看构建的思路:如果有新的品种只需修改提供方,应用方无需修改。

【1】、定义一个接口 Pizza

package com.yintong.principle.singleresponsibility;
//将Pizza 做成一个接口
public interface Pizza {
	//准备原材料, 不同的披萨不一样,因此,我们做成抽象方法
	public void prepare();
}

【2】、定义披萨的种类,实现 Pizza 接口,如下定义了 GREEK、CHEESE 两种披萨。如果后续有新的种类可以实现 Pizza 接口,继续添加新的品种。

//希腊披萨
public class GreekPizza implements Pizza{

	@Override
	public void prepare() {
		System.out.println(" 给希腊披萨 准备原材料 ");
	}
}
//奶酪披萨
public class CheesePizza implements Pizza{

	@Override
	public void prepare() {
		System.out.println(" 给制作奶酪披萨 准备原材料 ");
	}
}

【3】、 创建一个简单的工厂类对象 SimpleFactory

public class SimpleFactory {
	//传入 orderType(种类) 返回对应的 Pizza 对象
	public Pizza createPizza(String orderType) {
		Pizza pizza = null;
		//使用简单工厂模式
		if (orderType.equals("greek")) {
			//希腊披萨
			pizza = new GreekPizza();
		} else if (orderType.equals("cheese")) {
			//奶酪披萨 
			pizza = new CheesePizza();
		} 
		return pizza;
	}
}

【4】、在应用代码 OrderPizza 中调用工厂类,获取用户需要的披萨对象。

public class OrderPizza {
	//定义用户要获取的披萨类型
	private static final String pizza = "greek";
	public static void main(String[] args) {
		//通过工厂获取希腊披萨
		SimpleFactory simpleFactory = new SimpleFactory();
		//greekPizza 就是我们需要获取的目标披萨
		Pizza greekPizza = simpleFactory.createPizza(pizza);
		//调用目标披萨的方法
		greekPizza.prepare();
	}
}

二、工厂模式的优缺点


优点:1)、一个调用者想创建一个对象,只要知道其名称就可以了。
2)、扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以。
3)、屏蔽产品的具体实现,调用者只关心产品接口。

缺点:每增加一个产品时,都需要增加一个具体实现类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。这并不是什么好事。

注意事项:作为一种创建类模式,在任何需要生成复杂对象的地方,都可以使用工厂方法模式。有一点需要注意的地方就是复杂对象适合使用工厂模式,而简单对象,特别只需要通过 new 就可以完成创建的对象,无需工厂模式。如果使用工厂模式就需要使用工厂类,会增加系统的复杂度。

三、抽象工厂方法模式


需求:在上述的基础上,添加了地区。例如:用户可以点北京的奶酪披萨,北京的胡椒披萨,或者伦敦的奶酪披萨,伦敦的胡椒披萨。
工厂方法设计模式:1)、定义一个 interface(工厂的接口) 用于创建相关或者依赖关系的对象簇,而无需指明具体对象类。
2)、从设计层面来看,抽象工厂模式就是简单工厂模式的改进(或者称为进一步抽象)。
3)、将工厂抽象成两层,AbsFactory(抽象工厂)和具体实现的工厂子类。程序员可以根据创建对象类型使用对应的工厂子类。这样将单个的简单工厂类变成了工厂簇,更有利于代码的维护和扩展。
类图:将简单工厂模式中的工厂类抽象成了一个接口,易于后期扩展。

【1】、定义工厂类的接口(AbsFactory)

//一个抽象工厂模式的抽象层(接口)
public interface AbsFactory {
	//让下面的工厂子类来 具体实现
	public Pizza createPizza(String orderType);
}

【2】、让北京和伦敦的工厂类实现此接口(与简单工厂类的区别就是实现了 AbsFactory 接口,伦敦略)

public class BJFactory implements AbsFactory{
	//更加orderType 返回对应的Pizza 对象
	public Pizza createPizza(String orderType) {
		Pizza pizza = null;
		//使用简单工厂模式
		if (orderType.equals("greek")) {
			//希腊披萨
			pizza = new GreekPizza();
		} else if (orderType.equals("cheese")) {
			//奶酪披萨 
			pizza = new CheesePizza();
		} 
		return pizza;
	}
}

【3】、在 Order 订单应用中,与接口 AbsFactory 进行组合。

public class OrderPizza {
	AbsFactory factory;
	//定义构造器
	public OrderPizza(AbsFactory factory){
		this.factory = factory;
	}
	//定义用户要获取的披萨类型,可以定义一个变量从客户端传入
	private static final String pizza = "greek";
	public void main(String[] args) {
		//greekPizza 就是我们需要获取的目标披萨
		Pizza greekPizza = factory.createPizza(pizza);
		//调用目标披萨的方法
		greekPizza.prepare();
	}
}

四、工厂模式在 JDK-Calendar 类中的应用


//1、调用 Calendar 对象
Calendar instance = Calendar.getInstance();
//2、进入 Calendar.getInstance() 方法
public static Calendar getInstance()
{
	return createCalendar(TimeZone.getDefault(),Locale.getDefault(Locale.Category.FORMAT));
}
//3、进入 createCalendar 方法
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) {
			//该出就是我们要重点查看的部分,根据用户需求,创建Calendar 对象
			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;
			}
		}
	}
	return cal;
}

五、工厂模式小结


1)、工厂模式的意义:将实例化对象的代码提取出来,放到一个类中统一管理和维护,达到和主项目的依赖关系的解耦。从而提高项目的扩展和维护性。
2)、设计模式依赖抽象原则:创建对象实例时,不要直接 new 类,而是把这个 new 类的动作放在一个工厂的方法中,并返回。不要让类继承具体类,而是继承抽象类或者实现 interface(接口)。不要覆盖基类中已经实现的方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值