工厂模式应用了多态,必须是一个父类或者接口派生的子类。由工厂返回父类的引用,指向不同的子类对象。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。
1. 简单工厂模式
简单工厂模式就是当我们使用类型参数调用类中的方法时, 该类会根据传入的参数来返回我们想要的值. 我们通过一个例子来了解简单工厂模式.
1.1 普通简单工厂
允许接口创建对象, 但不会暴露对象的创建逻辑.
interface Actor {// 演员类
void play();// 表演
}
class Dancer implements Actor {//舞蹈演员
@Override
public void play() {
System.out.println("我是舞者,我在跳舞");
}
}
class Singer implements Actor {//歌手
@Override
public void play() {
System.out.println("我是歌手,我在演唱");
}
}
public class ActorFactory {// 演员工厂
public Actor getActor(String type) {// 根据类型不同,返回不同的子类对象
if ("singer".equals(type)) {
return new Singer();
} else if ("dancer".equals(type)) {
return new Dancer();
} else {
System.out.println("类型不正确");
return null;
}
}
}
测试方法:
public static void main(String[] args) {
ActorFactory factory=new ActorFactory();
Actor actor=factory.getActor("dancer");
actor.play();
}
普通简单工厂的缺点是如果type字符串传错了,就不能得到想要的对象。多方法简单工厂对普通简单工厂进行了改进。
1.2 多方法简单工厂
多方法简单工厂里定义多个方法,每个方法返回不同的子类对象。
public class ActorFactory {// 演员工厂
public Actor getSigner() {
return new Singer();
}
public Actor getDancer() {
return new Dancer();
}
}
测试方法:
public static void main(String[] args) {
ActorFactory factory=new ActorFactory();
Actor actor=factory.getDancer();
actor.play();
}
1.3 多静态方法简单工厂
将多方法简单工厂的方法写成静态方法,在调用工厂时不需要创建工厂实例。多数情况下,我们开发时都会选择这种模式。
public static class ActorFactory {// 演员工厂
public Actor getSigner() {
return new Singer();
}
public static Actor getDancer() {
return new Dancer();
}
}
测试方法:
public static void main(String[] args) {
Actor actor= ActorFactory.getDancer();
actor.play();
}
2. 工厂方法模式
允许接口创建对象, 但使用哪个类来创建对象, 则交由子类决定的。在简单工厂中 ,如果增加新的产品,需要修改工厂类。违反了开闭原则。现在将工厂抽取出一个接口,即抽象工厂角色。而不同的产品由具体工厂角色来生产。当增加新产品的时候,只需要增加一个新的具体工厂即可。
1、定义了一个接口来创建对象, 但是工厂本身并不负责创建对象(上面的简单工厂需要创建对象的), 而是将这一任务交由子类完成, 子类决定了要实例化哪些类.
2、工厂方法的创建是通过继承而不是通过实例化来完成的.
3、工厂方法使设计更加具有可定制性. 可以返回相同的实例或子类, 而不是某种类型的对象. 下面看代码:
public interface ActorFactory {// 演员工厂接口
Actor produce();
}
public class DancerFactory implements ActorFactory {
@Override
public Actor produce() {
return new Dancer();
}
}
public class SingerFactory implements ActorFactory{
@Override
public Actor produce() {
return new Singer();
}
}
测试方法:
public static void main(String[] args) {
ActorFactory factory=new DancerFactory();
Actor actor=factory.produce();
actor.play();
}
3. 抽象工厂模式
抽象工厂一般用于产品族。是一个能够创建一系列相关的对象而无需指定其具体类的接口. 该模式能够提供其他工厂对象, 在其内部创建其他对象。抽象工厂模式主要目的是提供一个接口来创建一系列相关对象, 而无需指定具体的类. 工厂方法将创建实例的任务委托给了子类, 抽象工厂方法的目标是创建一系列相关对象.
假如车有宝马和奥迪(产品树)。商务车有宝马商务车和奥迪商务车,跑车有宝马跑车和奥迪跑车(产品族)。
抽象工厂是生产一个产品族的产品。
public interface Car {
void drive();
}
abstract class BMW implements Car{
}
class SportBMW extends BMW{
@Override
public void drive() {
System.out.println("我是宝马跑车");
}
}
class BusinessBMW extends BMW{
@Override
public void drive() {
System.out.println("我是宝马商务车");
}
}
abstract class Audi implements Car{
}
class SportAudi extends Audi{
@Override
public void drive() {
System.out.println("我是奥迪跑车");
}
}
class BusinessAudi extends Audi{
@Override
public void drive() {
System.out.println("我是奥迪商务车");
}
}
public interface CarFactory {
BMW createBMW();
Audi createAudi();
}
class SportCarFactory implements CarFactory {
@Override
public BMW createBMW() {
return new SportBMW();
}
@Override
public Audi createAudi() {
return new SportAudi();
}
}
class BusinessCarFactory implements CarFactory {
@Override
public BMW createBMW() {
return new BusinessBMW();
}
@Override
public Audi createAudi() {
return new BusinessAudi();
}
}
public static void main(String[] args) {
CarFactory factory=new BusinessCarFactory();
Car car=factory.createAudi();
car.drive();
}
工厂模式优点:
1、松耦合, 对象的创建可以独立于类的实现. 2、客户端无需了解创建对象的类, 但照样可以使用它来创建对象.
只需要知道需要传递的接口, 方法, 参数, 就可以创建所需类型的对象了. 3、可以轻松在工厂中添加其他类来创建其他类型对象,
而无需更改客户端代码. 简单情况下, 客户端只需要传递另一个参数即可. 4、工厂可以重用现有对象. 但是, 若客户端直接创建对象的话,
总是创建一个新对象.