工厂模式的三种变种:简单工厂模式(也称静态工厂模式),工厂方法模式,抽象工厂模式
一,静态工厂模式
定义:通过专门定义一个工厂类负责创建其他类的实例,被创建的实例具有共同的父类。
三种角色:
- 工厂角色(SimpleFactory),负责创建所有类的内部逻辑。
- 抽象产品角色(IProduct),工厂角色所创建的所有对象的父类,这里所说的父类可以时接口也可以是抽象类,它负责描述所有实例所共有的公共接口。
- 具体产品角色(Concrete Product),工厂角色所创建的具体实例对象,这些具体的产品具有共同的父类。
示例代码:
抽象产品角色:
public interface IFood {
void eat();
}
具体产品角色:
public class McChiken implements IFood {
@Override
public void eat() {
System.out.println("Eating McChiken");
}
}
public class Chips implements IFood {
@Override
public void eat() {
System.out.println("Eating chips");
}
}
工厂角色:
public class Mcdonlad {
public static IFood getFood(String name) {
switch (name) {
case "chip":
return new Chips();
case "mcChiken":
return new McChiken();
default:
System.out.println("Food cannot be provided");
return null;
}
}
}
测试类:
public class McClient {
public static void main(String[] args) {
IFood chip = Mcdonlad.getFood("chip");
IFood mcChiken = Mcdonlad.getFood("mcChiken");
IFood kfcChiken = Mcdonlad.getFood("kfcChiken");
if (chip != null) chip.eat();
if (mcChiken != null) mcChiken.eat();
if (kfcChiken != null) kfcChiken.eat();
}
}
缺点:
工厂类集中所有实例的创建逻辑,当需要增加同一个产品类的产品时,就要修改工厂类,这违背了“开放封闭原则”,即违背了“对扩展开放,对修改关闭”的原则。
另外,当需要增加不同产品类的产品时,工厂类就无法做到,因为抽象产品角色已经确定了所生产的产品类。例如,当前的抽象产品类是生产Food类型的产品,当需要生产Drink类型的产品时,就做不到了。
实际应用:
JDBC,数据库编程接口API,它是Java应用程序与各类关系型数据库进行对话的一种机制,用JDBC进行数据库访问时,要使用数据库厂商提供的驱动程序接口与数据库管理系统进行数据交互。
二,工厂方法模式
四种角色:
工厂接口,工厂接口时工厂方法的核心,与调用者直接交互用来提供产品。
工厂实现,工厂实现决定如何实例化产品,是实现扩展的途径,需要有多少种产品,就需要有多少个具体的工厂类实现。
产品接口,是定义产品的规范,所有的产品都必须遵循产品接口定义的规范。
产品实现,实现产品接口的具体类,决定了产品在客户端中的具体行为。
实例代码:
工厂接口
public interface IStore {
IChip getChips();
}
产品接口
public interface IChip {
void eat();
}
产品实现
public class KfcChip implements IChip {
@Override
public void eat() {
System.out.println("Eating KFC Chips");
}
}
public class McChip implements IChip {
@Override
public void eat() {
System.out.println("Eating McdonladStore Chips");
}
}
工厂实现
public class KfcStore implements IStore {
@Override
public IChip getChips() {
return new KfcChip();
}
}
public class McdonladStore implements IStore {
@Override
public IChip getChips() {
return new McChip();
}
}
测试类
public class FactoryMethodClient {
public static void main(String[] args) {
IStore mcStore = new McdonladStore();
mcStore.getChips().eat();
IStore kfcStore = new KfcStore();
kfcStore.getChips().eat();
}
}
优点:
在工厂方法中,用户只需要知道所要产品的具体工厂,无须关心具体的创建过程。
增加新产品时,只需要添加一个具体产品类和对应的实现工厂,无需对原工厂进行任何修改,符合“开闭原则”。
缺点:
每次增加一个产品时,都要添加一个具体产品类和对应的实现工厂,类的个数成倍增加。
与简单工厂模式的对比:
核心工厂类不再负责具体产品的创建,而是将具体的创建工作交给子类去完成。
三,抽象工厂模式
抽象工厂模式可以描述针对N种产品,M家公司各自有自己的产品线。
比如,作为手机厂商,华为和小米都可以生产手机和平板。
示例代码:
抽象工厂类
public interface IPhoneCorp {
IPhone productPhone();
IPad productPad();
}
具体工厂类
public class XiaomiCorp implements IPhoneCorp {
@Override
public IPhone productPhone() {
return new XiaomiPhone();
}
@Override
public IPad productPad() {
return new XiaomiPad();
}
}
public class HuaweiCorp implements IPhoneCorp {
@Override
public IPhone productPhone() {
return new HuaweiPhone();
}
@Override
public IPad productPad() {
return new HuaweiPad();
}
}
抽象产品类
public interface IPad {
void getPadDescription();
}
public interface IPhone {
void getPhoneDescription();
}
具体产品类
public class XiaomiPad implements IPad {
@Override
public void getPadDescription() {
System.out.println("This is XiaomiPad 8");
}
}
public class XiaomiPhone implements IPhone {
@Override
public void getPhoneDescription() {
System.out.println("This is Xiaomi 8s");
}
}
public class HuaweiPad implements IPad {
@Override
public void getPadDescription() {
System.out.println("This is Huawei Pad 10");
}
}
public class HuaweiPhone implements IPhone {
@Override
public void getPhoneDescription() {
System.out.println("This is Huawei P20");
}
}
总结:
抽象工厂模式时工厂方法模式的升级版,它用来创建一组相关或相互依赖的对象。与工厂方法模式的区别在于,工厂方法模式针对的是一个产品等级结构;而抽象工厂模式则是针对多个产品等级结构。换句话说,工厂方法模式提供的所有产品都是衍生自同一个接口或抽象类,而抽象工厂模式所提供的产品则是衍生自不同的接口或抽象类。