最近在看IOC实现,IOC的具体实现是抽象工厂的一次很好的使用。在这就记录一下抽象工厂的原理。
不得不提的是在工厂模式这一家族中有三类:
- 简单工厂模式
- 工厂方法模式
- 抽象工厂模式
定义
简单工厂模式
《JAVA与模式》一书中是这样定义的:简单工厂模式是类的创建模式,又可以叫做静态工厂模式。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。
工厂方法模式
工厂方法模式是类的创建模式(当然其他两种工厂模式都是,还有单例,建造者,原型)。工厂方法模式的用意是定义一个创建产品对象的工厂接口,将实际创建工作放到子类中去,避免违背开闭原则。
抽象工厂模式
该模式有一个讲的非常详细的博客,我这就不写了:http://www.cnblogs.com/java-my-life/archive/2012/03/28/2418836.html
抽象工厂模式是面向多个产品等级的
类图及实现
简单工厂模式
用例场景:现在我们要实现一个简单的抓取网页的小程序,在爬取网页的时候可以有多种方式:1.自己编程Socket发HTTP请求抓取;2.利用HttpUrlConnection抓取;3.也可以利用HttpClient抓取等。
类图:
实现:
//ICrawler接口
public interface ICrawler {
public String crawler(String url);
}
//可以看做爬虫类实现的一种"产品"
public class SocketCrawlerImp implements ICrawler{
@Override
public String crawler(String url) {
// TODO Auto-generated method stub
return "SocketCrawlerImp";
}
}
//可以看做爬虫类实现的一种"产品"
public class HttpUrlConnectionCrawlerImp implements ICrawler{
@Override
public String crawler(String url) {
// TODO Auto-generated method stub
return "HttpUrlConnectionCrawlerImp";
}
}
//工厂类,用于根据输入的类型实例化爬虫产品类
public class CrawlerFactory {
public static ICrawler factory(String type){
type = type.toLowerCase();
if(type.equals("socket")){
return new SocketCrawlerImp();
}else if (type.equals("httpurlconnection")) {
return new HttpUrlConnectionCrawlerImp();
}else {
throw new RuntimeException("输入类型有误!");
}
}
}
//测试类
public class User {
public static void main(String[] args) {
ICrawler crawler = CrawlerFactory.factory("Socket");
String content = crawler.crawler("http://www.9zhai.com");
System.out.println(content);
}
}
//输出:SocketCrawlerImp
根据上面的实现可以看到,我们在User(即与用户打交道)类中,我们不需要关系底层实现细节,根据不同的需求可以用工厂生产出不同的产品。现在回头看看定义,是不是一目了然?
工厂方法模式
用例场景:和简单工厂模式相同~
类图:在画类图之前,我们可以考虑一下,简单工厂方法模式的优缺点,优点不用说了,缺点是违背了开闭原则,而工厂方法模式就是为了解决这个问题的,方法是:我们定义个工厂接口,将产品类的实例化下放到改接口的子类中去。
实现:
//ICrawler接口
public interface ICrawler {
public String crawler(String url);
}
//可以看做爬虫类实现的一种"产品"
public class SocketCrawlerImp implements ICrawler{
@Override
public String crawler(String url) {
// TODO Auto-generated method stub
return "SocketCrawlerImp";
}
}
//可以看做爬虫类实现的一种"产品"
public class HttpUrlConnectionCrawlerImp implements ICrawler{
@Override
public String crawler(String url) {
// TODO Auto-generated method stub
return "HttpUrlConnectionCrawlerImp";
}
}
//工厂接口
public interface ICrawlerFactory {
ICrawler factory();
}
//SocketCrawler工厂
public class SocketCrawlerFactory implements ICrawlerFactory{
@Override
public ICrawler factory() {
// TODO Auto-generated method stub
return new SocketCrawlerImp();
}
}
//HttpUrlConnectionCrawlerFactory 工厂
public class HttpUrlConnectionCrawlerFactory implements ICrawlerFactory{
@Override
public ICrawler factory() {
// TODO Auto-generated method stub
return new HttpUrlConnectionCrawlerImp();
}
}
//测试类
public class User {
public static void main(String[] args) {
ICrawlerFactory factory = new SocketCrawlerFactory();
ICrawler crawler = factory.factory();
String content = crawler.crawler("http://www.9zhai.com");
System.out.println(content);
}
}
//输出:SocketCrawlerImp
抽象工厂模式
优缺点
简单工厂模式
优点:
- 简单明了,对用户来说,达到需求即可,不需要关心细节
- 易于扩展,当我们需要增加一种实现方式,如HttpClient的时候,我们只需要实现一个类实现ICrawler接口即可
缺点:
- 当不停的增加产品类的时候,可能造成工厂类的臃肿
- 当增加HttpClient实现的时候,在工厂类中需要增加if代码段,违背了开闭原则
工厂方法模式
优点:
- 解决了简单工厂模式遇到的问题:违背开闭原则
缺点:
- 当产品大量时,工厂子类和产品子类都需要增加,大量的话容易造成臃肿,所以一般情况下和简单工厂模式配合使用(即将产品子类分为多类,在工厂子类中一个工厂子类对应一类产品子类,在这个工厂子类使用if或者switch来判断使用这一类中的哪个产品)
- 当产品多于一个产品族的时候,使用该种模式可能会产生不兼容的情况,具体请看抽象工厂模式
- -