工厂模式:工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。
工厂模式分为简单工厂模式、工厂方法模式、抽象工厂模式。
1、简单工厂模式
简单工厂模式将对象的创建与对象使用分割开来,对不同类对象的创建用工厂类包装起来,客户要创建对象只要告诉工厂对象即可。
我们用Office的那几个软件举个例子:
//office接口
public interface Office {
public void work();
}
//Word实现类
public class Word implements Office {
@Override
public void work() {
System.out.println("我是word,可以编辑文字。。。");
}
}
//Excel实现类
public class Excel implements Office {
@Override
public void work() {
System.out.println("我是Excel,可以编辑表格。。。");
}
}
//工厂类
public class SimpleFactory {
public Office creatOffice(String type) {
if(type.equals("Excel")){
return new Excel();
} else if (type.equals("Word"))
return new Word();
return null;
}
}
//客户端演示
public class Client {
public static void main(String[] args) {
SimpleFactory factory = new SimpleFactory();
Office o = factory.creatOffice("Word");
o.work();
o = factory.creatOffice("Excel");
o.work();
}
}
其UML类图如下
可以看出,随着产品的增加,工厂类要修改,判定也会越来越复杂。我们可以用反射的方式来写工厂的创建对象方法:
public class SimpleFactory {
public <T extends Office> T creatOffice(Class<T> c) {
Office o = null;
try {
o = (T) Class.forName(c.getName()).newInstance();
} catch (Exception e) {
System.out.println("创建对象失败。。。");
}
return (T) o;
}
}
但反射比较慢,难免影响程序性能。
2、工厂方法模式
在简单工厂模式中,我们每次增加一个产品类,都要去修改工厂类,不符合开闭原则,而且所有对象都要一个工厂创建,工厂业务较重,逻辑较复杂。工厂方法模式很好的解决了这个问题。
我们继续用office这个例子说说怎么解决的。
//office接口
public interface Office {
public void work();
}
//Word实现类
public class Word implements Office {
@Override
public void work() {
System.out.println("我是word,可以编辑文字。。。");
}
}
//Excel实现类
public class Excel implements Office {
@Override
public void work() {
System.out.println("我是Excel,可以编辑表格。。。");
}
}
//工厂接口
public interface Factory {
public Office create();
}
//Word工厂实例
public class WordFactory implements Factory {
@Override
public Office create() {
return new Word();
}
}
//Excel工厂实例
public class ExcelFactory implements Factory {
@Override
public Office create() {
return new Excel();
}
}
//客户端演示
public class Client {
public static void main(String[] args) {
Factory wordFactory = new WordFactory();
Office word = wordFactory.create();
word.work();
Factory excelFactory = new ExcelFactory();
Office excel = excelFactory.create();
excel.work();
}
}
UML图:
如果再添加产品,则只要再加一个新的类与它的工厂即可,不用动里面代码,符合开闭原则,但加一种产品就要多写两个类,多了会使系统过于复杂。
3、抽象工厂模式
当有多个抽象产品时,工厂方法模式就不适用了,比如我们再配上操作系统,word在win10上运行,excel在linux上运行,这时就轮到我们的抽象工厂显身手了,抽象工厂模式是所有形式的工厂模式中 最为抽象和最具一般性的一种形态。
抽象工厂模式(Abstract Factory Pattern) : 提供一个 创建一系列相关或相互依赖对象的接口 ,而 无须指定它们具体的类 。抽象工厂模式又称为Kit 模式 ,属于 对象创建型模式
我们用office和操作系统演示一下抽象工厂模式。
//抽象系统类
public interface ISystem {
public void work();
}
//系统实现类
public class Windows implements ISystem {
@Override
public void work() {
System.out.println("在windows上工作。。。");
}
}
public class Linux implements ISystem {
@Override
public void work() {
System.out.println("在Linux上工作。。。");
}
}
//抽象office类
public interface Office {
public void work();
}
//office实现类
public class Word implements Office {
@Override
public void work() {
System.out.println("我是word,可以编辑文字。。。");
}
}
public class Excel implements Office {
@Override
public void work() {
System.out.println("我是Excel,可以编辑表格。。。");
}
}
//抽象工厂类
public interface Factory {
public Office getOffice();
public ISystem getSystem();
}
//工厂实现类
public class ExcelFactory implements Factory {
@Override
public Office getOffice() {
return new Excel();
}
@Override
public ISystem getSystem() {
return new Linux();
}
}
public class WordFactory implements Factory {
@Override
public Office getOffice() {
return new Word();
}
@Override
public ISystem getSystem() {
return new Windows();
}
}
//客户测试类
public class Client {
public static void main(String[] args) {
//生产word与word所用的系统
Factory wordFactory = new WordFactory();
Office word = wordFactory.getOffice();
ISystem system = wordFactory.getSystem();
word.work();
system.work();
}
}
UML类图
加上依赖关系
可以看出,若要加上一个抽象产品的话,比如再为这些系统搭配不同的平台,pc端,安卓端,就要大改,违背开闭原则。但增加新的具体产品可以,比如我再加上Ubuntu系统,加上PowerPoint,只要加上类和 他们的工厂就可以了,符合开闭原则。
总结
无论是简单工厂模式,工厂方法模式,还是抽象工厂模式,他们都属于工厂模式,在形式和特点上也是极为相似的。在使用时,我们不必去在意这个模式到底工厂方法模式还是抽象工厂模式,实际应用时能解决问题满足需求即可,可灵活变通,无所谓高级与低级。
此外无论哪种模式,由于可能封装了大量对象和工厂创建,新加产品需要修改已定义好的工厂相关的类,因此对于产品和工厂的扩展不太友好,利弊需要权衡一下。