欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

设计模式之简单工厂

程序员文章站 2024-01-21 18:20:28
...

例如有一家服装厂,可以生产各种上衣,目前可以生产商务上衣和时尚上衣。
接口和类的设计如下:
接口:Coat

public interface Coat {
	void makeCoat();
}

商务上衣类:

public class BusinessCoat implements Coat {

	@Override
	public void makeCoat() {
		System.out.println("business coat maked");
		
	}

}

时尚上衣类:

public class FashionCoat implements Coat {

	@Override
	public void makeCoat() {
		System.out.println("fashion coat maked");
	}

}

有经销商从该工厂购入服装,工厂为其生产需要的服装种类。
客户端类:

public class Client {
	public static void main(String[] args) {
		Coat coat1 = new BusinessCoat();
		Coat coat2 = new FashionCoat();
		coat1.makeCoat();
		coat2.makeCoat();
		
	}
}

在Client中,直接使用到了接口Coat的实现类BusinessCoat和FashionCoat,破坏了封装隔离的原则。
现在我们使用简单工厂模式创建Factory类,如下:

public class CoatFactory {
	private CoatFactory() {};
	
	public static Coat createCoat(int i) {
		Coat coat = null;
		if(i == 1) {
			coat =  new BusinessCoat();
		}else if(i == 2) {
			coat =  new FashionCoat();
		}
		return coat;
		
	}
}

通常我们把工厂类设计为工具类,私有化其构造器,把其中的方法设置为静态方法;创建好工厂类之后,将Client进行改造,如下:

	public class Client {
	public static void main(String[] args) {
		Coat coat1 = CoatFactory.createCoat(1);
		Coat coat2 = CoatFactory.createCoat(2);
		coat1.makeCoat();
		coat2.makeCoat();
		
	}
}

通过创建工厂类CoatFactory,将Coat接口和其实现类(BusinessCoat 和FashionCoat)封装到一起,使其与Client类隔离,实现面向接口编程的目的。但是Client在调用createCoat方法时,需要传入参数,参数不同返回的实现类不同,这样Clinet必须知道参数的具体含义,所以不得不把createCoat中的部分实现细节暴露给客户端Client。针对这样的问题,我们可以把参数配置化,写入到配置文件中。
配置类CreateCoat.properties,内容如下:

CoatClass=day04.FashionCoat

改造CoatFactory,如下:

public class CoatFactory {
   private CoatFactory() {};
   
   public static Coat createCoat() {
   	//加载配置文件
   	Properties p = new Properties();
   	InputStream in = null;
   	try {
   		in = CoatFactory.class.getResourceAsStream("CreateCoat.properties");
   		p.load(in);
   	} catch (IOException e) {
   		// TODO Auto-generated catch block
   		e.printStackTrace();
   	}
   	//根据配置,利用反射,创建实例
   	Coat coat = null;
   	try {
   		 coat = (Coat) Class.forName(p.getProperty("CoatClass")).newInstance();
   	} catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
   		// TODO Auto-generated catch block
   		e.printStackTrace();
   	}
   	return coat;
   	
   }
}

经过如上改造后,Client在使用CoatFactory时,如下:

public class Client {
   public static void main(String[] args) {
   	Coat coat = CoatFactory.createCoat();
   	coat.makeCoat();
   	
   }
}

可以看出,经过改造,将Coat接口和其实现类封装到了一起,Client也已经和Coat接口隔离,实现了面向接口编程。通过将参数配置文件化,使整个程序也符合开发的开闭原则。当该工厂决定新增休闲上衣的生产时,我们可以新建CasualCoat类,并为不同的经销商配置相应的Coat实现类即可。

何时选用简单工厂?
1.如果想完全封装隔离具体实现,让外部只通过接口来操作封装体,那可以选用简单工厂,让客户端通过工厂来获取相应的接口,而无需关心具体实现。

2.如果想把对外创建对象的职责集中管理和控制,可以选择简单工厂,一个简单工厂可以创建很多的,甚至时不相关的对象,可以把对外创建对象的职责集中的一个简单工厂中来,从而实现集中管理和控制。