简单工厂
简单工厂模式(Simple Factory Pattern)属于类的创新型模式,又叫静态工厂方法模式(Static FactoryMethod Pattern),是通过专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。不属于GOF 23种设计模式。
优点:解耦,简单工厂适用于工厂类负责创建对象较少的场景;客户只需要传入工厂类的参数,对于如何创建类的逻辑不需要关系。
缺点:工厂类的职责过重,不易于扩展过于复杂的产品结构。
例子:
public interface ISimple {
void output();
}
public class SimpleA implements ISimple{
@Override
public void output() {
System.out.println("输出:SimpleA");
}
}
public class SimpleB implements ISimple{
@Override
public void output() {
System.out.println("输出:SimpleB");
}
}
public class SimpleFactory {
public ISimple outputObject(Class<? extends ISimple> clazz){
try {
return clazz.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
public class Test {
public static void main(String [] args){
SimpleFactory simpleFactory=new SimpleFactory();
ISimple simple = simpleFactory.outputObject(SimpleB.class);
simple.output();
}
}
输出:SimpleB
类图:
源码例子:
JDK源码例子:
类:java.util.Calendar
方法: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;
}
日志源码例子:
类:org.slf4j.LoggerFactory
private Logger logger = LoggerFactory.getLogger(getClass());
public static Logger getLogger(String name) {
ILoggerFactory iLoggerFactory = getILoggerFactory();
return iLoggerFactory.getLogger(name);
}
工厂方法模式
工厂方法模式(Factory Method)是指定义一个创建对象的接口;让实现这个接口的类来决定实例化那个类,工厂方法让类的实例化推迟到子类进行,在工厂方法模式中用户只需关心所需产品对应的工厂,无需关心创建细节,而且加入新的产品符合开闭原则。工厂方法模式主要解决产品扩展问题,在简单工厂中;随着产品链的丰富,如果每个创建对象逻辑有区分的话。工厂职责会变得越来越多,有点像万能工厂。不易维护。根据单一职责原则将职能继续拆分;专人干专事。
优点:客户端不依赖产品类实例如何被创建、实现等细节。一个类通过其子类来指定创建那个对象。
缺点:累的个数增多;增加系统复杂度。增加了系统的抽象性和理解难度。
例子:
public interface ISimpleFactory {
public ISimple create();
}
public class SimpleAFactory implements ISimpleFactory{
@Override
public ISimple create() {
return new SimpleA();
}
}
public class SimpleBFactory implements ISimpleFactory{
@Override
public ISimple create() {
return new SimpleB();
}
}
public class Test {
public static void main(String [] args){
ISimpleFactory simpleFactory=new SimpleAFactory();
ISimple iSimple = simpleFactory.create();
iSimple.output();
}
}
输出:SimpleA
类图:
抽象工厂
抽象工厂模式(Abstract Factory Pattern) 是指提供一个创建一系列相关或相互依赖对象的接口。无需指定他们具体的类。客户端不依赖于产品类实例如何被创建、实现等细节。强调的是一系列相关产品对象(属于同一产品族)一起使用创建对象需大量重复的代码。需要提供一个产品类的库;所有产品以同意的接口出现,而是客户端不依赖于具体实现
从上图中我们看到面包、薯条、可乐3种零食。相同零食代表一个产品族。麦当劳、I mlovein it卖的面包、薯条、可乐代表产品等级结构。
代码例子:
//定义产品等级
public interface IBread {
//生产面包
void produce();
}
public interface ICola {
//生产可乐
void produce();
}
public interface IFrenchFries {
//生产薯条
void produce();
}
public class Bread implements IBread{
@Override
public void produce() {
System.out.println("选择面包");
}
}
public class Cola implements ICola{
@Override
public void produce() {
System.out.println("选择可乐");
}
}
public class FrenchFries implements IFrenchFries {
@Override
public void produce() {
System.out.println("选择薯条");
}
}
//定义抽象工厂
public abstract class ProduceFactory {
public void init(){
System.out.println("初始化数据");
}
protected abstract IBread createBread();
protected abstract ICola createCola();
protected abstract IFrenchFries createFrenchFries();
}
//定义产品族
//I M Love It具体实现工厂
public class IMLoveItFactory extends ProduceFactory{
@Override
protected IBread createBread() {
super.init();
return new Bread();
}
@Override
protected ICola createCola() {
return new Cola();
}
@Override
protected IFrenchFries createFrenchFries() {
return new FrenchFries();
}
}
//麦当劳具体实现工厂
public class McDonaldsFactory extends ProduceFactory{
@Override
protected IBread createBread() {
return new Bread();
}
@Override
protected ICola createCola() {
return new Cola();
}
@Override
protected IFrenchFries createFrenchFries() {
return new FrenchFries();
}
}
public class Test {
public static void main(String [] args){
System.out.println("麦当劳生产------------------");
ProduceFactory mcDonaldsFactory=new McDonaldsFactory();
mcDonaldsFactory.createBread().produce();
mcDonaldsFactory.createCola().produce();
mcDonaldsFactory.createFrenchFries().produce();
System.out.println("I M Love It生产------------------");
ProduceFactory imLoveItFactory=new IMLoveItFactory();
imLoveItFactory.createBread().produce();
imLoveItFactory.createCola().produce();
imLoveItFactory.createFrenchFries().produce();
}
}
输出:
麦当劳生产------------------
选择面包
选择可乐
选择薯条
I M Love It生产------------------
初始化数据
选择面包
选择可乐
选择薯条
类图:
优点:
1、最大的好处便是易于交换产品系列,由于具体工厂类,在一个应用中只需要在初始化的时候出现一次,这就使得改变一个应用的具体工厂变得非常容易,它只需要改变具体工厂即可使用不同产品配置。
2、它让具体的创建实例过程与客户端分离,客户端是通过它们的抽象接口操作实例,产品的具体类名也被具体工厂的实现分离,不会出现在客户代码中。
缺点:
1、规定了所有可能被创建的产品集合、产品族扩展新的产品困难,需要修改抽象工厂的接口。
2、增加了系统的抽象性和理解难度
总结:在实际需求中产品等级结构升级是非常正常的事情。我们可以根据实际情况,只要不是频繁升级,可以不遵循开闭原则。代码每半年升级一次或每年升级一次又有何不可呢。
来源:oschina
链接:https://my.oschina.net/u/4483459/blog/3198133