一 简单工厂
1️⃣概念
定义:由一个工厂对象决定创建出哪一种产品类的实例;
类型:创建型,但不属于GOF23种设计模式;
2️⃣适用场景
工厂类负责创建的对象比较少;
客户端(应用层)只知道传入工厂类的参数,对于如何创建对象(逻辑)不关心;
3️⃣优点
只需要传入一个正确的参数,就可以获取你所需要的对象,而无需知道其创建细节;
4️⃣缺点
工厂类的职责相对过重,增加新的产品需要修改工厂类的判断逻辑,违背了开闭原则;
无法形成基于继承的等级结构;
5️⃣简单工厂Coding
①创建Video抽象类
public abstract class Video {
public abstract void produce();
}
②创建实现类来实现Video类
// JavaVideo
public class JavaVideo extends Video {
@Override
public void produce() {
System.out.println("录制Java课程视频");
}
}
// PythonVideo
public class PythonVideo extends Video {
@Override
public void produce() {
System.out.println("录制Python课程视频");
}
}
③创建简单工厂类
public class VideoFactory {
// 使用反射来提高扩展性
public Video getVideo(Class c){
Video video = null;
try {
video = (Video) Class.forName(c.getName()).newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return video;
}
// 传统方式创建对象
public Video getVideo(String type){
if("java".equalsIgnoreCase(type)){
return new JavaVideo();
}else if("python".equalsIgnoreCase(type)){
return new PythonVideo();
}
return null;
}
}
④编写测试类
public class Test {
public static void main(String[] args) {
// VideoFactory videoFactory = new VideoFactory();
// Video video = videoFactory.getVideo("java");
// if(video == null){
// return;
// }
// video.produce();
VideoFactory videoFactory = new VideoFactory();
Video video = videoFactory.getVideo(JavaVideo.class);
if(video == null){
return;
}
video.produce();
}
}
⑤UML类图
6️⃣应用简单工厂的JDK类(java.util.calendar源码)
/**
* Gets a calendar using the default time zone and locale. The
* Calendar
returned is based on the current time
* in the default time zone with the default
* {@link Locale.Category#FORMAT FORMAT} locale.
*
* @return a Calendar.
*/
public static Calendar getInstance()
{
return createCalendar(TimeZone.getDefault(), Locale.getDefault(Locale.Category.FORMAT));
}
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) {
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;
}
}
}
if (cal == null) {
// If no known calendar type is explicitly specified,
// perform the traditional way to create a Calendar:
// create a BuddhistCalendar for th_TH locale,
// a JapaneseImperialCalendar for ja_JP_JP locale, or
// a GregorianCalendar for any other locales.
// NOTE: The language, country and variant strings are interned.
if (aLocale.getLanguage() == "th" && aLocale.getCountry() == "TH") {
cal = new BuddhistCalendar(zone, aLocale);
} else if (aLocale.getVariant() == "JP" && aLocale.getLanguage() == "ja"
&& aLocale.getCountry() == "JP") {
cal = new JapaneseImperialCalendar(zone, aLocale);
} else {
cal = new GregorianCalendar(zone, aLocale);
}
}
return cal;
}
二 工厂方法
1️⃣概念
定义:定义一个创建对象的接口,但让实现接口的这个类来决定实例化哪个类,工厂方法让类的实例化推迟到子类中进行;
类型:创建性
2️⃣适用的场景
创建对象需要大量重复的代码;
客户端(应用层)不依赖于产品类实例如何被创建 实现等细节;
一个类通过其子类来指定创建哪个对象;
3️⃣优点
用户只需关心所需产品对应的工厂,无需关心创建细节;
加入新产品符合开闭原则,提高可扩展性;
4️⃣缺点
类的个数容易过多,增加复杂度;
增加了系统的抽象性和理解难度;
5️⃣工厂方法Coding
①创建产品类抽象类Video
public abstract class Video {
public abstract void produce();
}
②创建具体的产品类来实现抽象类
public class FEVideo extends Video{
@Override
public void produce() {
System.out.println("录制FE课程视频");
}
}
public class JavaVideo extends Video {
@Override
public void produce() {
System.out.println("录制Java课程视频");
}
}
public class PythonVideo extends Video {
@Override
public void produce() {
System.out.println("录制Python课程视频");
}
}
③创建产品抽象工厂类VideoFactory
public abstract class VideoFactory {
public abstract Video getVideo();
}
④创建具体的产品工厂类实现产品抽象工厂
public class FEVideoFactory extends VideoFactory{
@Override
public Video getVideo() {
return new FEVideo();
}
}
public class JavaVideoFactory extends VideoFactory {
@Override
public Video getVideo() {
return new JavaVideo();
}
}
public class PythonVideoFactory extends VideoFactory {
@Override
public Video getVideo() {
return new PythonVideo();
}
}
⑤创建测试类
public class Test {
public static void main(String[] args) {
VideoFactory videoFactory = new PythonVideoFactory();
VideoFactory videoFactory2 = new JavaVideoFactory();
VideoFactory videoFactory3 = new FEVideoFactory();
Video video = videoFactory.getVideo();
video.produce();
}
}
⑥UML类图
6️⃣应用工厂方法的JDK类(java.util.collection)
①java.util.collection
public interface Collection extends Iterable {
// Query Operations
/**
* Returns the number of elements in this collection. If this collection
* contains more than Integer.MAX_VALUE elements, returns
* Integer.MAX_VALUE.
*
* @return the number of elements in this collection
*/
int size();
/**
* Returns true if this collection contains no elements.
*
* @return true if this collection contains no elements
*/
boolean isEmpty();
/**
* Returns true if this collection contains the specified element.
* More formally, returns true if and only if this collection
* contains at least one element e such that
* (o==null ? e==null : o.equals(e)).
*
* @param o element whose presence in this collection is to be tested
* @return true if this collection contains the specified
* element
* @throws ClassCastException if the type of the specified element
* is incompatible with this collection
* (optional)
* @throws NullPointerException if the specified element is null and this
* collection does not permit null elements
* (optional)
*/
boolean contains(Object o);
/**
* Returns an iterator over the elements in this collection. There are no
* guarantees concerning the order in which the elements are returned
* (unless this collection is an instance of some class that provides a
* guarantee).
*
* @return an Iterator over the elements in this collection
*/
Iterator iterator();
....
}
②ArrayList(由于源码太长,此处省略了大部分源码)
public class ArrayList extends AbstractList
implements List, RandomAccess, Cloneable, java.io.Serializable
{
/**
* Returns an iterator over the elements in this list in proper sequence.
*
* The returned iterator is fail-fast.
*
* @return an iterator over the elements in this list in proper sequence
*/
public Iterator iterator() {
return new Itr();
}
/**
* An optimized version of AbstractList.Itr
*/
private class Itr implements Iterator {
int cursor; // index of next element to return
int lastRet = -1; // index of last element returned; -1 if no such
int expectedModCount = modCount;
Itr() {}
public boolean hasNext() {
return cursor != size;
}
@SuppressWarnings("unchecked")
public E next() {
checkForComodification();
int i = cursor;
if (i >= size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[lastRet = i];
}
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
ArrayList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
@Override
@SuppressWarnings("unchecked")
public void forEachRemaining(Consumer super E> consumer) {
Objects.requireNonNull(consumer);
final int size = ArrayList.this.size;
int i = cursor;
if (i >= size) {
return;
}
final Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length) {
throw new ConcurrentModificationException();
}
while (i != size && modCount == expectedModCount) {
consumer.accept((E) elementData[i++]);
}
// update once at end of iteration to reduce heap write traffic
cursor = i;
lastRet = i - 1;
checkForComodification();
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
③UML类图
三 抽象工厂
1️⃣概念
定义:抽象工厂模式提供一个创建一系列相关或相互依赖对象的接口;
无需指定它们具体的类;
类型:创建型;
2️⃣适用场景
客户端(应用层)不依赖于产品类实例如何被创建 实现等细节;
强调一系列相关的产品对象(属于同一产品族)一起使用创建对象需要大量重复代码;
提供一个产品类的库,所有产品以同样的接口出现,从而使客户端不依赖于具体实现;
3️⃣优点
具体产品在应用层代码隔离,无须关心创建细节;
将一个系列的产品族统一到一起创建;
4️⃣缺点
规定了所有可能被创建的产品集合,产品族中扩展新的产品比较困难,需要修改抽象工厂的接口;
增加了系统的抽象性和理解难度;
5️⃣抽象工厂-产品等级结构与产品族
6️⃣抽象工厂Coding
①创建抽象工厂
public interface CourseFactory {
Video getVideo();
Article getArticle();
}
②创建具体工厂来实现抽象工厂
public class JavaCourseFactory implements CourseFactory {
@Override
public Video getVideo() {
return new JavaVideo();
}
@Override
public Article getArticle() {
return new JavaArticle();
}
}
public class PythonCourseFactory implements CourseFactory {
@Override
public Video getVideo() {
return new PythonVideo();
}
@Override
public Article getArticle() {
return new PythonArticle();
}
}
③创建抽象产品族
public abstract class Article {
public abstract void produce();
}
public abstract class Video {
public abstract void produce();
}
④创建具体产品
public class JavaArticle extends Article {
@Override
public void produce() {
System.out.println("编写Java课程手记");
}
}
public class JavaVideo extends Video {
@Override
public void produce() {
System.out.println("录制Java课程视频");
}
}
public class PythonArticle extends Article {
@Override
public void produce() {
System.out.println("编写Python课程手记");
}
}
public class PythonVideo extends Video {
@Override
public void produce() {
System.out.println("录制Python课程视频");
}
}
⑤创建测试类
public class Test {
public static void main(String[] args) {
CourseFactory courseFactory = new JavaCourseFactory();
Video video = courseFactory.getVideo();
Article article = courseFactory.getArticle();
video.produce();
article.produce();
}
}
⑥UML类图
7️⃣抽象工厂的应用
①org.apache.ibatis.session
package org.apache.ibatis.session;
import java.sql.Connection;
/**
* Creates an {@link SqlSession} out of a connection or a DataSource
*
* @author Clinton Begin
*/
public interface SqlSessionFactory {
SqlSession openSession();
SqlSession openSession(boolean autoCommit);
SqlSession openSession(Connection connection);
SqlSession openSession(TransactionIsolationLevel level);
SqlSession openSession(ExecutorType execType);
SqlSession openSession(ExecutorType execType, boolean autoCommit);
SqlSession openSession(ExecutorType execType, TransactionIsolationLevel level);
SqlSession openSession(ExecutorType execType, Connection connection);
Configuration getConfiguration();
}
②以SqlSession openSession(ExecutorType execType, TransactionIsolationLevel level)为例
③进入到DefaultSqlSessionFactory
@Override
public SqlSession openSession(ExecutorType execType, TransactionIsolationLevel level) {
return openSessionFromDataSource(execType, level, false);
}
④打开openSessionFromDateSource
private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
Transaction tx = null;
try {
final Environment environment = configuration.getEnvironment();
final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
final Executor executor = configuration.newExecutor(tx, execType);
return new DefaultSqlSession(configuration, executor, autoCommit);
} catch (Exception e) {
closeTransaction(tx); // may have fetched a connection so lets call close()
throw ExceptionFactory.wrapException("Error opening session. Cause: " + e, e);
} finally {
ErrorContext.instance().reset();
}
}
⑤UML类图