说一说你对工厂模式的理解

Wenhao 6月前 ⋅ 84 阅读

工厂模式的用意是定义一个创建产品对象的工厂接口,将实际创建性工作推迟到子类中。工厂模式可分为简单工厂、工厂方法和抽象工厂模式。注意,我们常说的23种经典设计模式,包含了工程方法模式和抽象工厂模式,而并未包含简单工厂模式。另外,我们平时说的工厂模式,一般默认是指工厂方法模式。

简单工厂

简单工厂模式其实并不算是一种设计模式,更多的时候是一种编程习惯。简单工厂的实现思路是,定义一个工厂类,根据传入的参数不同返回不同的实例,被创建的实例具有共同的父类或接口。简单工厂的适用场景是:

  • 需要创建的对象较少。

  • 客户端不关心对象的创建过程。

示例:

创建一个可以绘制不同形状的绘图工具,可以绘制圆形,正方形,三角形,每个图形都会有一个draw()方法用于绘图,不看代码先考虑一下如何通过该模式设计完成此功能。

由题可知圆形,正方形,三角形都属于一种图形,并且都具有draw方法,所以首先可以定义一个接口或者抽象类,作为这三个图像的公共父类,并在其中声明一个公共的draw方法:

public interface Shape {     void draw(); }

下面就是编写具体的图形,每种图形都实现Shape接口:

// 圆形 class CircleShape implements Shape {     public CircleShape() {         System.out.println("CircleShape: created");     }     @Override     public void draw() {         System.out.println("draw: CircleShape");     } } // 正方形 class RectShape implements Shape {     public RectShape() {        System.out.println("RectShape: created");     }     @Override     public void draw() {        System.out.println("draw: RectShape");     }  } // 三角形 public class TriangleShape implements Shape {     public TriangleShape() {         System.out.println("TriangleShape: created");     }     @Override     public void draw() {         System.out.println("draw: TriangleShape");     } }

下面是工厂类的具体实现:

 class ShapeFactory {           public static Shape getShape(String type) {               Shape shape = null;               if (type.equalsIgnoreCase("circle")) {                   shape = new CircleShape();               } else if (type.equalsIgnoreCase("rect")) {                   shape = new RectShape();               } else if (type.equalsIgnoreCase("triangle")) {                   shape = new TriangleShape();               }               return shape;           }    }

为工厂类传入不同的type可以new不同的形状,返回结果为Shape 类型,这个就是简单工厂核心的地方了。

工厂方法

工厂方法模式是简单工厂的仅一步深化, 在工厂方法模式中,我们不再提供一个统一的工厂类来创建所有的对象,而是针对不同的对象提供不同的工厂。也就是说每个对象都有一个与之对应的工厂。

工厂方法的实现思路是,定义一个用于创建对象的接口,让子类决定将哪一个类实例化。工厂方法模式让一个类的实例化延迟到其子类。

示例:

现在需要设计一个这样的图片加载类,它具有多个图片加载器,用来加载jpg,png,gif格式的图片,每个加载器都有一个read()方法,用于读取图片。下面我们完成这个图片加载类。

首先完成图片加载器的设计,编写一个加载器的公共接口:

public interface Reader {     void read(); }

然后完成各个图片加载器的代码:

// jpg图片加载器 class JpgReader implements Reader {     @Override     public void read() {         System.out.print("read jpg");     } } // png图片加载器 class PngReader implements Reader {     @Override     public void read() {         System.out.print("read png");     } } // gif图片加载器 class GifReader implements Reader {     @Override     public void read() {         System.out.print("read gif");     } }

现在我们按照定义所说定义一个抽象的工厂接口ReaderFactory:

interface ReaderFactory {
    Reader getReader();
}

里面有一个getReader()方法返回我们的Reader 类,接下来我们把上面定义好的每个图片加载器都提供一个工厂类,这些工厂类实现了ReaderFactory 。

// jpg加载器工厂
class JpgReaderFactory implements ReaderFactory {
    @Override
    public Reader getReader() {
        return new JpgReader();
    }
}
// png加载器工厂
class PngReaderFactory implements ReaderFactory {
    @Override
    public Reader getReader() {
        return new PngReader();
    }
}
// gif加载器工厂
class GifReaderFactory implements ReaderFactory {
    @Override
    public Reader getReader() {
        return new GifReader();
    }
}

在每个工厂类中我们都通过重写的getReader()方法返回各自的图片加载器对象。

和简单工厂对比一下,最根本的区别在于,简单工厂只有一个统一的工厂类,而工厂方法是针对每个要创建的对象都会提供一个工厂类,这些工厂类都实现了一个工厂基类。

下面总结一下工厂方法的适用场景:

  • 客户端不需要知道它所创建的对象的类。

  • 客户端可以通过子类来指定创建对应的对象。

抽象工厂

这个模式最不好理解,而且在实际应用中局限性也蛮大的,因为这个模式并不符合开闭原则。实际开发还需要做好权衡。抽象工厂模式是工厂方法的仅一步深化,在这个模式中的工厂类不单单可以创建一个对象,而是可以创建一组对象。这是和工厂方法最大的不同点。

抽象工厂的实现思路是,提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。抽象工厂和工厂方法一样可以划分为4大部分:

  • AbstractFactory(抽象工厂):声明了一组用于创建对象的方法,注意是一组。

  • ConcreteFactory(具体工厂):它实现了在抽象工厂中声明的创建对象的方法,生成一组具体对象。

  • AbstractProduct(抽象产品):它为每种对象声明接口,在其中声明了对象所具有的业务方法。

  • ConcreteProduct(具体产品):它定义具体工厂生产的具体对象。

示例:

现在需要做一款跨平台的游戏,需要兼容Android,Ios,Wp三个移动操作系统,该游戏针对每个系统都设计了一套操作控制器(OperationController)和界面控制器(UIController),下面通过抽闲工厂方式完成这款游戏的架构设计。

由题可知,游戏里边的各个平台的UIController和OperationController应该是我们最终生产的具体产品。所以新建两个抽象产品接口。

抽象操作控制器:

interface OperationController {
    void control();
}

抽象界面控制器:

interface UIController {
    void display();
}

然后完成各个系统平台的具体操作控制器和界面控制器。

Android:

class AndroidOperationController implements OperationController {
    @Override
    public void control() {
        System.out.println("AndroidOperationController");
    }
}
class AndroidUIController implements UIController {
    @Override
    public void display() {
        System.out.println("AndroidInterfaceController");
    }
}

IOS:

class IosOperationController implements OperationController {
    @Override
    public void control() {
        System.out.println("IosOperationController");
    }
}
class IosUIController implements UIController {
    @Override
    public void display() {
        System.out.println("IosInterfaceController");
    }
}

WP:

class WpOperationController implements OperationController {
    @Override
    public void control() {
        System.out.println("WpOperationController");
    }
}
class WpUIController implements UIController {
    @Override
    public void display() {
        System.out.println("WpInterfaceController");
    }
}

下面定义一个抽闲工厂,该工厂需要可以创建OperationController和UIController。

public interface SystemFactory {
    public OperationController createOperationController();
    public UIController createInterfaceController();
}

在各平台具体的工厂类中完成操作控制器和界面控制器的创建过程。

Android:

public class AndroidFactory implements SystemFactory {
    @Override
    public OperationController createOperationController() {
        return new AndroidOperationController();
    }
    @Override
    public UIController createInterfaceController() {
        return new AndroidUIController();
    }
}

IOS:

public class IosFactory implements SystemFactory {
    @Override
    public OperationController createOperationController() {
        return new IosOperationController();
    }
    @Override
    public UIController createInterfaceController() {
        return new IosUIController();
    }
}

WP:

public class WpFactory implements SystemFactory {
    @Override
    public OperationController createOperationController() {
        return new WpOperationController();
    }
    @Override
    public UIController createInterfaceController() {
        return new WpUIController();
    }
}

下面总结一下抽象工厂的适用场景:

  • 和工厂方法一样客户端不需要知道它所创建的对象的类。

  • 需要一组对象共同完成某种功能时。并且可能存在多组对象完成不同功能的情况。

  • 系统结构稳定,不会频繁的增加对象。


全部评论: 0

    我有话说: