导语
在日常开发中,一般而言是很少涉及到设计模式的,或者说很多时候就算接触到了设计模式,很多人或许却并不知道自己遇见了设计模式。所以在这次这个系列的文章中,还是想简单的介绍一下一些设计模式,以及这些设计模式的概念、适用场景等等。其中只用少量的文字来叙述,大部分还是用代码来展示,因为个人觉得这样其实才是最直接的。对于在文章中,可能还涉及一些jdk源码或一些框架中应用了哪些设计模式,进行一些简单的概述以及代码的展示。
一、简单工厂定义和类型
定义:由一个工厂对象决定创建出哪一种产品类的实例。
类型:创建型(其实是不属于GOF23种设计模式中的)
二、简单工厂的使用场景与优缺点
适用场景:
- 工厂类负责创建的对象比较少
- 客户端(应用层)只知道传入工厂类的参数对于如何创建对象(逻辑)不关心
优点:只需要传入正确的参数,就可以获取你所需要的对象,而无需知道其创建细节。
缺点:工厂类的职责相对过重,增加新的产品需要修改工厂类的判断逻辑,违背开闭原则。
三、简单工厂模式UML图
代码具体实现如下:
1.首先定义一个抽象冰箱类:
public abstract class Fridge {
public abstract void produce();
}
2.再定义两个相关的品牌冰箱的实现类:
public class GeLiFridge extends Fridge {
@Override
public void produce() {
System.out.println("-----生产格力空调-----");
}
}
public class PanasonicFridge extends Fridge {
@Override
public void produce() {
System.out.println("-----生产松下冰箱-----");
}
}
3.创建冰箱的工厂类
这里在冰箱工厂类中使用两种方式去实现,一种是使用传入参数类型,一种是传入具体要创建的类(在一定程度上满足开闭原则,因为在新增需要创建类的时候,不需要修改工厂类)。
public class FridgeFactory {
// 2.传入具体需要创建的类
public Fridge getFridge(Class c) {
Fridge fridge = null;
try {
fridge = (Fridge) Class.forName(c.getName()).newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return fridge;
}
// 1.传入参数类型
public Fridge getFridge(String type) {
if("geli".equals(type)) {
return new GeLiFridge();
}else if ("panasonic".equals(type)) {
return new PanasonicFridge();
}
return null;
}
}
4.测试类
public class MainTest {
public static void main(String[] args) {
// 2.传入具体需要创建的类
FridgeFactory fridgeFactory =new FridgeFactory();
Fridge fridge = fridgeFactory.getFridge(GeLiFridge.class);
if (fridge == null) {
return;
}
fridge.produce();
// 1.传入参数类型
FridgeFactory ff =new FridgeFactory();
Fridge f = ff.getFridge("geli");
if (f == null) {
return;
}
f.produce();
}
}
测试结果:
四、简单工厂方法在JDK源码中的体现
在JDK中有体现这样的简单工厂这样的设计代码,先在IDEA中找到Calendar类(使用Ctrl+Shift+N),然后找到这个类中的getInstance(TimeZone zone)这个方法(Ctrl + F12)。
public static Calendar getInstance()
{
return createCalendar(TimeZone.getDefault(), Locale.getDefault(Locale.Category.FORMAT));
}
从上面代码中,可以得知这个方法是一个静态方法,在这个方法里调用了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 (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;
}
上面这段代码中,在最后判断if (cal == null)这个代码块中,有对国家语言进行判断。相比较上面自己创建的工厂类中的第一种类型,也是对传入的类型进行一个简单的判断,只是这里的createCalendar方法是静态的,因为这里已经满足了需求,并不需要考虑它的扩展性的。接下来我们也看下这个类的UML图:
从上面的UML类图中,可以看出Calendar实现了三个接口,还有集成Calendar这个类的两个子类。而Calendar自身是一个抽象类,在上图中的符号也能看出来。
版权声明:尊重博主原创文章,转载请注明出处:https://blog.csdn.net/zfy163520