工厂模式是一种统称,有三类工厂模式,下面分别介绍。
一、简单工厂
简单工厂并不是一种真正的的设计模式,其更像是一种编程习惯。主要就是创建一个类,让其负责对象的创建。(工厂类中,根据条件决定一个抽象产品类(接口)由哪个具体产品类来实现。)
类图:
优点:
1、将对象的创建封装在这一个类里面,若以后修改创建的对象,只需要修改这一个类即可。使代码更容易维护。
2、将创建实例的工作与使用实例的工作分开,使用者不必关心类对象如何创建,实现了解耦。
缺点:
1、扩展性差,如果是静态工厂的话,难以通过继承改变方法的行为。
2、当创建不同的对象需要不同的额外参数时,难以操作(通过方法重载应该也可以操作,可能比较复杂)。
二、工厂方法模式
定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。
类图:
优点:
1、符合开-闭原则。新增一种产品时,只需要增加相应的具体产品类和相应的工厂子类即可。简单工厂模式需要修改工厂类的判断逻辑
工厂模式是简单工厂模式的进一步抽象和拓展,在保留了简单工厂的封装优点的同时,让扩展变得简单,让继承变得可行,增加了多态性的体现。
缺点:
1、每次新增一个或多个具体产品类,也要同时新增一个具体工厂类或者修改现有工厂类,修改现有工厂类则不符合开-闭原则,新增具体工厂类会使得代码复杂化。
实例:
一个包含工厂方法的抽象类,其实现了除工厂方法外的其它产品操作方法:
public abstract class Creator {
String name;
public void work(){
Product p=createProduct(name);
p.work();
}
//参数化工厂方法,通常情况下一个工厂只生产一个产品,不需要参数化
public abstract Product createProduct(String name);
}
子类A实现了工厂方法创建实例:
public class CreatorA extends Creator{
public CreatorA(String name){
this.name=name;
}
@Override
public Product createProduct(String name) {
if(name.equals("A"))
return new ProductA();
if(name.equals("B"))
return new ProductB();
return null;
}
}
子类B实现了工厂方法创建实例:
public class CreatorB extends Creator{
public CreatorB(String name){
this.name=name;
}
@Override
public Product createProduct(String name) {
if(name.equals("C"))
return new ProductC();
return null;
}
}
产品接口:
public interface Product {
public abstract void work();
}
具体产品A:
public class ProductA implements Product{
@Override
public void work() {
System.out.println("A is working!");
}
}
具体产品B:
public class ProductB implements Product{
@Override
public void work() {
System.out.println("B is working!");
}
}
具体产品C:
public class ProductC implements Product{
@Override
public void work() {
System.out.println("HAHAHA, I am C, a new product!");
}
}
测试代码:
public class Test {
public static void main(String[] args) {
Creator cr=new CreatorA("A");
cr.work();
Creator cr2=new CreatorB("C");
cr2.work();
Creator cr3=new CreatorA("B");
cr3.work();
}
}
运行结果:
A is working!
HAHAHA, I am C, a new product!
B is working!
三、抽象工厂
抽象工厂模式提供一个接口,用于创建相关或者依赖对象的家族,而不需要明确指定具体的类。
抽象工厂允许客户使用抽象的接口来创建一组相关的产品,而不需要知道实际产出的具体产品是什么。
类图:
优点:
1、工厂和产品都是面向接口编程,非常符合面向对象原则。
缺点:
1、产品族的扩展将是一件十分费力的事情,假如产品族中需要增加一个新的产品,则几乎所有的工厂类都需要进行修改。所以使用抽象工厂模式时,对产品等级结构的划分是非常重要的。
实例:
一个抽象的工厂:
public interface AbstractFactory {
public abstract ProductA createProductA();
public abstract ProductB createProductB();
}
两个具体的工厂:
public class Factory1 implements AbstractFactory{
@Override
public ProductA createProductA() {
return new ProductA1();
}
@Override
public ProductB createProductB() {
return new ProductB1();
}
}
public class Factory2 implements AbstractFactory{
@Override
public ProductA createProductA() {
return new ProductA2();
}
@Override
public ProductB createProductB() {
return new ProductB2();
}
}
一个抽象产品A:
public interface ProductA {
public abstract void work();
}
两个具体产品A:
public class ProductA1 implements ProductA{
@Override
public void work() {
System.out.println("This is A1, over!");
}
}
public class ProductA2 implements ProductA{
@Override
public void work() {
System.out.println("This is A2, over!");
}
}
一个抽象产品B:
public interface ProductB {
public abstract void work();
}
两个具体产品B:
public class ProductB1 implements ProductB{
@Override
public void work() {
System.out.println("This is B1!");
}
}
public class ProductB2 implements ProductB{
@Override
public void work() {
System.out.println("This is B2!");
}
}
下面是测试代码:
public class Processor {
AbstractFactory factory;
public Processor(AbstractFactory factory){
this.factory=factory;
}
public void process(){
ProductA pa=factory.createProductA();
System.out.println("ProductA is producted!");
pa.work();
ProductB pb=factory.createProductB();
System.out.println("ProductB is producted!");
pb.work();
}
}
public class Test {
public static void main(String[] args) {
AbstractFactory factory=new Factory1();
Processor pr=new Processor(factory);
pr.process();
pr=new Processor(new Factory2());
pr.process();
}
}
运行结果为:
ProductA is producted!
This is A1, over!
ProductB is producted!
This is B1!
ProductA is producted!
This is A2, over!
ProductB is producted!
This is B2!