有一个水果加工工厂,我们的需求是实现加工水果的功能。常见的做法是创建一个水果抽象类,写一个抽象的加工方法,然后创建具体的水果类去继承抽象类,再去实现抽象方法,最后客户端再去新建对象实例。
public abstract class Fruit {
abstract void make();
}
public class Apple extends Fruit{
@Override
void make() {
System.out.println("加工苹果");
}
}
public class Pear extends Fruit {
@Override
void make() {
System.out.println("加工雪梨");
}
}
public class Customer {
public static void main(String[] args) {
Apple a=new Apple();
Pear p=new Pear();
a.make();
p.make();
}
}
这种做法的缺点是将用户和水果紧密耦合了,用户需要知道创建水果对象的过程,如果创建对象的过程比较复杂,那么客户端每次需要创建对象时将写入大段的代码。因此,我们需要定义一个创建对象的类,由这个类专门生成这个对象的实例,这就引出了工厂模式
工厂模式可以分为三类:
1)简单工厂模式(Simple Factory)
2)工厂方法模式(Factory Method)
3)抽象工厂模式(Abstract Factory)
简单工厂模式
简单工厂模式:定义了一个创建对象的类,由这个类来封装实例化对象
对于上面的例子,我们不改动水果类的代码,只需要创建一个简单工厂类去产生水果的实例
public class SimpleFactory {
public static Fruit create(String type){
Fruit fruit=null;
if(type=="apple")
fruit=new Apple();
if(type=="pear")
fruit=new Pear();
return fruit;
}
}
客户端使用
public class Customer {
public static void main(String[] args) {
Apple a=(Apple)SimpleFactory.create("apple");
Pear p= (Pear)SimpleFactory.create("pear");
a.make();
p.make();
}
}
这样对象的创建就被简单工厂类封装起来了,用户不需要了解创建对象的过程,达到了解耦的目的。
但是简单工厂模式违反了开闭原则,即对扩展开放、对修改关闭。如果需要新增加水果种类,那么就必须要新增if语句。
适用场景
1、需要创建的对象较少
2、客户端不关心对象的创建过程
简单工厂类的角色分配
1、抽象产品角色
所有产品的父类,描述所有实例共有的方法
2、具体产品角色
简单工厂类的创建目标,具体实现了抽象产品的方法
3、工厂角色
负责实现创建所有实例的内部逻辑,工厂类可以被外部调用,创建所需的产品对象
2、工厂方法模式
工厂方法模式不再使用统一的工厂类去新建每一个对象,而是创建一个工厂抽象类,然后再针对每一个具体的产品类去创建一个具体的工厂类。
工厂类
public interface Factory {
Fruit create(String type);
}
public class AppleFactory implements Factory {
@Override
public Fruit create(String type) {
Apple apple=new Apple();
return apple;
}
}
public class PearFactory implements Factory{
@Override
public Fruit create(String type) {
Pear p=new Pear();
return p;
}
}
客户端
public class Customer {
public static void main(String[] args) {
Factory factory=new AppleFactory();
Factory factory1=new PearFactory();
Apple a=(Apple)factory.create("apple");
Pear p=(Pear)factory1.create("pear");
a.make();
p.make();
}
}
这样的好处是当有新的水果种类时只需要新创建一个工厂类而不需要修改工厂类的代码。但是也带来了问题,每增加一个产品类就需要新创建一个工厂类,增加了开发的工作量。
适用场景
1、客户端不关心对象的创建过程,只需要了解创建对象的具体工厂子类
工厂类的角色分配
1、抽象产品角色
所有产品的父类,描述所有实例共有的方法
2、具体产品角色
具体实现了抽象产品的方法,每个产品类都对应一个工厂类
3、抽象工厂角色
定义了创建实例的接口,所有工厂类都要实现这个接口
4、具体工厂角色
实现抽象工厂接口的具体工厂类,包含创建某一种产品对象的逻辑。
抽象工厂模式
抽象工厂不仅仅可以生产一种产品,而是可以生产一组产品,这些产品是互相关联的。
现在有一个工厂需要生产水果和果汁,那么就需要抽象工厂。抽象工厂与普通工厂的区别是一个工厂对象可以创建一组相关的对象,而普通工厂是一个工厂对象只能创建一种对象。
产品类
public abstract class Fruit {
abstract void make();
}
public class Apple extends Fruit {
@Override
void make() {
System.out.println("加工苹果");
}
}
public abstract class Juice {
public abstract void make();
}
public class AppleJuice extends Juice {
@Override
public void make() {
System.out.println("制作苹果汁");
}
}
工厂类
public interface Factory {
Fruit createFruit();
Juice createJuice();
}
public class AppleFactory implements Factory {
@Override
public Fruit createFruit() {
Apple a=new Apple();
return a;
}
@Override
public Juice createJuice() {
AppleJuice j=new AppleJuice();
return j;
}
}
客户端
public class Customer {
public static void main(String[] args) {
Factory factory=new AppleFactory();
Apple a=(Apple)factory.createFruit();
AppleJuice appleJuice=(AppleJuice) factory.createJuice();
a.make();
appleJuice.make();
}
}
适用场景
1、需要创建一组对象去实现功能。
2、系统结构稳定,不会频繁增加对象,如果一旦增加对象,那么就需要再抽象工厂类中修改代码,违反了开闭原则。