简单工厂
定义
- 由工厂对象决定创建出哪一种产品类的实例。
类型
- 创建型,但不属于GOF(Gang of Four)23种设计模式。抽象工厂和工厂方法也都是源于此。
适用场景
- 工厂类负责创建的对象比较少。
- 客户端或者是应用层只知道传入工厂类的参数,对于如何创建对象(逻辑)不关心。
优点
- 只需要传入一个正确的参数就可以获取你需要的对象,而无需知道其他创建的细节。
缺点
- 工厂类的职责相对过重,增加新的产品,需要修改工厂类的判断逻辑,不符合开闭原则。
举例
public class Test {
public static void main(String[] args) {
Book book = new EnglishBook();
book.read();
// Book book = new MathBook();
// book.read();
}
}
在这个设计的框架中,我们可以看到,每一次我想要不同的书的对象,我得自己去import,去new,感觉这样不太好对不对~
接下来让我们来瞅瞅简单工厂是如何操作的:
public class Test {
public static void main(String[] args) {
BookFactory bookFactory = new BookFactory();
Book book = bookFactory.getBook("math");
if (book == null) return;
book.read();
}
}
public class BookFactory {
public Book getBook(String bookName) {
if ("math".equals(bookName)) {
return new MathBook();
} else if ("english".equals(bookName)) {
return new EnglishBook();
}
return null;
}
}
这里我们新搞了一个类,叫作BookFactory,这个类的作用呢,就是根据参数创建对应需要的具体类,相对于一个工厂,这样的话,我们就省去了在应用层创建类的细节。当然,这个工厂类的获取方法也可以写为静态的,但这样就不能被继承后覆盖来进行扩展咯。
最后,不得不强调的是,在工厂类的方法的实现中,可以看到,如果我们需要添加语文书,化学书,这个时候我们是需要修改那个判断逻辑的,显然,这不符合开闭原则。不过,在后面的抽象工厂和工厂方法中会再次讨论这玩意。
客官不要走!
还有好东西,既然提出了不合理的地方,我们寻思着是不是可以先就地解决一下?
好!反射登场!
public class BookFactory {
public static Book getBook(Class c) {
Book book = null;
try {
book = (Book) Class.forName(c.getName()).newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return book;
}
}
public class Test {
public static void main(String[] args) {
Book book = BookFactory.getBook(EnglishBook.class);
if(book == null) return;
book.read();
}
}
这样是不是也算实现了开闭原则~如果对反射不熟悉的小伙伴可以出门左转问谷歌。
号外号外,有兴趣的小伙伴可以瞅瞅java.util.Calendar的getInstance()方法、java.sql.DriverManeger的getConnection()方法(JDBC的反射:Class.forName(“com.jdbc.mqsql.Driver”)和org.slf4j.LoggerFactory的getLogger()方法,具体在LoggerContext的getLogger()那。