工厂模式
工厂模式细分三种:简单工厂模式、工厂模式、抽象工厂模式。
工厂模式相当于抽象了简单工厂模式的工厂类,而抽象工厂模式在工厂模式的基础上加上了产品族的概念。
简单工厂模式
定义
又名静态方法模式,是由一个工厂对象决定创建出哪一种产品类的实例。
实现
用生产手机为例,假设有小米手机、华为手机两个类型的手机。
我们先定义手机的基类
interface IPhone {
void call();
}
然后实现小米、华为两个手机类
class MiPhone implements IPhone {
@Override
public void call() {}
}
class HwPhone implements IPhone {
@Override
public void call() {}
}
接着,我们创建一个简单工厂类
class PhoneFactory {
public static IPhone phone;
public static IPhone produce(String phoneType) {
switch (phoneType) {
case "mi":
phone = new MiPhone();
break;
case "huawei":
phone = new HwPhone();
break;
default:
phone = null;
}
return phone;
}
}
这样外部可以传入不同的字符串来调用工厂类的静态方法创建不同具体产品类的实例
IPhone miPhone = PhoneFactory.produce("mi");
IPhone HwPhone = PhoneFactory.produce("huawei");
UML图是
image.png
简单工厂模式的运用,可以使创建实例和使用实例的过程分开,使用不用关心类对象如何创建的,实现了解耦。但如果要添加新产品,就要修改工厂类的逻辑,造成工厂内部逻辑过于复杂,且违背了“开放-关闭”原则
工厂模式
根据上述所说,简单工厂模式,在增加新的产品时,需要修改我们的工厂类,违反了对扩展开放、对修改的关闭的原则。由此,产生了工厂模式。
工厂模式的思想是将工厂类抽象出一个基类,根据不同的产品,创建不同的工厂类。
定义
在工厂方法模式中,核心的工厂类不再负责所有的产品的创建,而是将具体创建的工作交给子类去做。该核心类成为一个抽象工厂角色,仅负责给出具体工厂子类必须实现的接口,而不接触哪一个产品类应当被实例化这种细节。
实现
还是用生产手机为例,假设有小米手机、华为手机两个类型的手机。
我们先定义手机的基类
interface IPhone {
void call();
}
然后实现小米、华为两个手机类
class MiPhone implements IPhone {
@Override
public void call() {}
}
class HwPhone implements IPhone {
@Override
public void call() {}
}
上面和简单工厂模式相同,接下来我们先创建一个工厂类的接口,让不同的子类去实现它。
interface IPhoneFactory {
IPhone produce();
}
然后创建生产小米手机的工厂类和生产华为手机的工厂类去实现 PhoneFactory
class MiPhoneFactory implements IPhoneFactory {
@Override
public IPhone produce() {
return new MiPhone();
}
}
class HwPhoneFactory implements IPhoneFactory {
@Override
public IPhone produce() {
return new HwPhone();
}
}
这样外部可以通过创建不同的工厂类来生产不同的产品,在增加新的产品时,不会修改原有的代码,只需要创建新的产品类实现产品接口,创建新的产品工厂类实现工厂接口。
IPhone miPhone = new MiPhoneFactory().produce();
IPhone hwPhone = new HwPhoneFactory().produce();
UML图是
image.png
工厂模式和简单工厂模式一样,对使用者而言,不需要关心产品实例的创建过程,只需要关心产品的接口。
抽象工厂模式
定义
为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类。
这一组相关或者相互依赖的对象有一个名词来形容就是产品族。
实现
还是生产手机的例子,为了解释产品族,我们要新增一类产品—手机套,小米、华为手机的手机两个手机套是不一样的。
我们先定义手机的接口
interface IPhone {
void call();
}
然后实现小米、华为两个手机类
class MiPhone implements IPhone {
@Override
public void call() {}
}
class HwPhone implements IPhone {
@Override
public void call() {}
}
定义手机套的接口
interface IPhoneCase {
void call();
}
然后实现小米、华为两个手机套类
class MiPhoneCase implements IPhoneCase {
@Override
public void protect() {}
}
class HwPhoneCase implements IPhoneCase {
@Override
public void protect() {}
}
因为手机和手机套之间不能混用,所以对应的工厂生产对应的手机套是最合适的。
我们先创建工厂接口,其中定义了两个方法,用于生成不用的产品。
interface IPhoneFactory {
IPhone producePhone();
IPhoneCase producePhoneCase();
}
然后创建生产小米手机的工厂类和生产华为手机的工厂类去实现 PhoneFactory
class MiPhoneFactory implements IPhoneFactory {
@Override
public IPhone producePhone() {
return new MiPhone();
}
@Override
public IPhoneCase producePhoneCase() {
return new MiPhoneCase();
}
}
class HwPhoneFactory implements IPhoneFactory {
@Override
public IPhone producePhone() {
return new HwPhone();
}
@Override
public IPhoneCase producePhoneCase() {
return new HwPhoneCase();
}
}
抽象工厂模式除了具有工厂方法模式的优点外,最主要的优点就是可以在类的内部对产品族进行约束。所谓的产品族,一般或多或少的都存在一定的关联,抽象工厂模式就可以在类内部对产品族的关联关系进行定义和描述,而不必专门引入一个新的类来进行管理。