铲屎官的“设计模式”打通教程

设计模式之零五:“无脑狂写的”抽象工厂

2018-04-27  本文已影响1人  c2aa1d94244a

阅读本篇大概需要 7 分钟。

首先,这个系列的文章在微信公众号:皮克啪的铲屎官 上全部都有,欢迎大家关注。

惯例,先说正事儿:

每日一皮克啪

皮克啪最近主打瘦身长图题材,各种高挑身材一览无余。皮克啪身体展开是防盗门的宽度。

WechatIMG55.jpeg

正事儿说完,咱们来聊聊抽象工厂模式
抽象工厂模式,应该是算是工厂模式里面的一种,是一种创造类型的模式。Wikipedia解释如下:
“The abstract factory pattern provides a way to encapsulate a group of individual factories that have a common theme without specifying their concrete classes.”
大致意思就是,抽象工厂模式为创建一组相关或者是相互依赖的对象提供一个接口,而不是指定他们的具体类
所以,一般来说,抽象工厂模式,会有多个具体的工厂类,而且每个工厂类负责产生自己对应的产品。这些具体工厂类都是继承自一个抽象工厂类,而且他们的生产的产品,也是继承自一个抽象产品类。
抽象工厂的UML图如下:

W3sDesign_Abstract_Factory_Design_Pattern_UML.jpg

可以看到,抽象工厂模式还是那四个角色,抽象工厂具体工厂抽象产品具体产品。只不过,这里具体工厂不在是只有一个,而是可以有好几个,工厂类里面的创造方法应该是包含所有产品的。是哪个产品的创建工厂,就实现对应产品的创造方法就可以。

一般来说,抽象工厂方法使用场景不是很多,当出现一个对象族有相同的约束时,可以使用抽象工厂模式。

操作实例

假设,PeekPa有个堂妹,叫PeekTataPeekTata的妈妈是PeekPa的姑姑,叫PeekAunt,那么我们在算上PeekMom,就有四个类,归整一下,PeekPaPeekTata算是产品,而PeekAuntPeekMom生了两个小崽子,所以,这两个应该算是工厂。产品的抽象类叫IPeekCat,工厂的抽象类叫IPeekFactory。那么利用抽象工厂模式,他们的结构大致如下:

抽象工厂类:

// 抽象工厂类
public abstract class IPeekFactory {
    // 生产PeekPa的抽象方法
    abstract IPeekCat bornPeekPa();
    // 生产PeekTata的抽象方法
    abstract IPeekCat bornPeekTata();
}

具体工厂类PeekMom:

// 负责生产PeekPa的具体工厂类
public class PeekMom extends IPeekFactory {
    public String name;

    public PeekMom() {
        this.name = this.getClass().getSimpleName();
    }
    // PeekMom只负责生产PeekPa,所以这里只实现ornPeekPa()
    @Override
    IPeekCat bornPeekPa() {
        IPeekCat peekPa = new PeekPa(this.name);
        // 调用产品内部方法
        peekPa.init();
        return peekPa;
    }
    // 空实现
    @Override
    IPeekCat bornPeekTata() {
        return null;
    }
}

具体工厂类PeekAunt:

// 负责生产PeekTata的具体工厂类
public class PeekAunt extends IPeekFactory {
    public String name;

    public PeekAunt() {
        this.name = this.getClass().getSimpleName();
    }
    // 空实现
    @Override
    IPeekCat bornPeekPa() {
        return null;
    }
    // PeekAunt只负责生产PeekTata,所以这里只实现bornPeekTata()方法
    @Override
    IPeekCat bornPeekTata() {
        IPeekCat peekTata = new PeekTata(this.name);
        // 调用产品内部方法
        peekTata.init();
        return peekTata;
    }
}

接下来是产品类别,产品抽象类IPeekCat

// 抽象产品类IPeekCat
abstract class IPeekCat {
    public String name;
    public int gender;
    public String mother;
    abstract void init();
    abstract void showInfo();
}

下面是具体产品类PeekPa

// 具体产品类PeekPa
public class PeekPa extends IPeekCat {

    public PeekPa(String mother) {
        this.mother = mother;
    }

    @Override
    void init() {
        this.name = this.getClass().getSimpleName();
        this.gender = 1;
    }

    @Override
    void showInfo() {
        System.out.println("This is: " + this.name + "\ngender: " + (this.gender == 0 ? "Female" : "Male") + "\nMother is: " + this.mother);
    }
}

下面是具体产品类PeekTata

// 具体产品类PeekTata
public class PeekTata extends IPeekCat {

    public PeekTata(String mother) {
        this.mother = mother;
    }

    @Override
    void init() {
        this.name = this.getClass().getSimpleName();
        this.gender = 0;
    }

    @Override
    void showInfo() {
        System.out.println("This is: " + this.name + "\ngender: " +  (this.gender == 0 ? "Female" : "Male") + "\nMother is: " + this.mother);
    }
}

啊,这项我们就有了几个类,抽象工厂类IPeekFactory, 具体工厂类PeekMomPeekAunt,抽象产品类IPeekCat,具体两个产品PeekPaPeekTata。那么我们实战调用工厂方法,创建两个对象,并且检验调用结果的代码如下:

    // 创建具体工厂对象
    IPeekFactory peekMom = new PeekMom();
    IPeekFactory peekAunt = new PeekAunt();
    // 调用工厂对象,来创建产品实例
    IPeekCat peekPa = peekMom.bornPeekPa();
    IPeekCat peekTata = peekAunt.bornPeekTata();
    // 调用内部方法验证
    peekPa.showInfo(); // This is: PeekPa
                       // gender: Male 
                       // Mother is: PeekMom
    peekTata.showInfo(); // This is: PeekTata
                         // gender: Female
                         // Mother is: PeekAunt

看到打印出来的结果,没有问题,那么我们看到,客户端只是简单的调用工厂的方法,就可以拿到产品的实例对象。而且客户端是看不到产品的构建方法的,耦合性低。

总结一下

抽象工厂模式是一种很方便,结构清晰的设计模式。有好处也有坏处。

优点:结构简单清晰,对问题高度抽象,当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。

缺点:由于有很多具体工厂类的存在,使得项目的类的数量会过于庞大,扩展性不是很好,如果要添加新的产品,需要改动所有工厂类。

所以,使用起来,依情况而定。啦啦啦啦啦啦~

请大家关注一下我的公众号:皮克啪的铲屎官

qr_code.png

是一个日更的微信公众号,每天都有新知识,大家一起交流进步。

上一篇下一篇

猜你喜欢

热点阅读