设计模式之简单工厂
例如有一家服装厂,可以生产各种上衣,目前可以生产商务上衣和时尚上衣。
接口和类的设计如下:
接口: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.如果想把对外创建对象的职责集中管理和控制,可以选择简单工厂,一个简单工厂可以创建很多的,甚至时不相关的对象,可以把对外创建对象的职责集中的一个简单工厂中来,从而实现集中管理和控制。
上一篇: JavaScript设计模式之工厂模式