23种设计模式(二)抽象工厂模式

本文介绍

学习抽象工厂模式(Abstract Factory)

抽象工厂模式介绍

抽象工厂模式是所有形态的工厂模式中最为抽象和最具一般性的一种形态。
抽象工厂模式是指当有多个抽象角色时,使用的一种工厂模式。
抽象工厂模式可以向客户端提供一个接口,
使客户端在不必指定产品的具体的情况下,
创建多个产品族中的产品对象。根据里氏替换原则,任何接受父类型的地方,
都应当能够接受子类型。因此,实际上系统所需要的,
仅仅是类型与这些抽象产品角色相同的一些实例,而不是这些抽象产品的实例。
换言之,也就是这些抽象产品的具体子类的实例。
工厂类负责创建抽象产品的具体子类的实例

当每个抽象产品都有多于一个的具体子类的时候,工厂角色怎么知道实例化哪一个子类呢?比如每个抽象产品 [1] 角色都有两个具体产品。抽象工厂模式提供两个具体工厂角色,分别对应于这两个具体产品角色,每一个具体工厂角色只负责某一个产品角色的实例化。每一个具体工厂类只负责创建抽象产品的某一个具体子类的实例。
每一个模式都是针对一定问题的解决方案,工厂方法模式针对的是一个产品等级结构;而抽象工厂模式针对的是多个产品等级结构。

角色

1、抽象工厂

2、具体工厂

3、抽象产品

4、具体产品

5、产品使用者

说明:

具体工厂“继承”抽象工厂;

具体产品”继承“抽象产品;

每个具体工厂(如PC工厂)包含若干个子工厂方法(如cpu工厂方法、显卡工厂方法…),子工厂方法负责生产对应的具体子产品,所有具体子产品(cpu、内存、显卡…)组合成一个具体产品(如惠普XXX型号PC);

产品使用者使用每个具体工厂生产的具体产品;

代码介绍

具体的实例代码:

1.抽象产品:衣服、裤子

1、衣服
package com.test.demo;

/**
 *
 * @author test
 */
public interface Clothes {
    /**
     * 获得名字
     */
    void printName();

}

2、裤子

package com.test.demo;

/**
 *
 * @author test
 */
public interface Pants {
    /**
     * 获得名字
     */void printName();

}

2.具体产品:花花公子衣服、花花公子裤子、七匹狼衣服、七匹狼裤子

1、花花公子衣服

package com.test.demo;

/**
 *
 * @author test
 */

public class PlayBoyClothes implements Clothes{

    private String name;
    public PlayBoyClothes(String name) {
        this.name = name;
        System.out.println("create a PlayBoyClothes.");
    }
    /**
     * @return the name
     */
    public String getName() {
        return name;
    }
    /**
     * @param name the name to set
     */
    public void setName(String name) {
        this.name = name;
    }

    @Override
    public void printName() {
        System.out.println(this.getClass().getName() + ":" + this.name);

    }
}

2、花花公子裤子

package com.test.demo;

/**
 *
 * @author test
 */

public class PlayBoyPants implements Pants{
    private String name;
    public PlayBoyPants(String name) {
        this.name = name;
        System.out.println("create a PlayBoyPants.");
    }
    /**
     * @return the name
     */
    public String getName() {
        return name;
    }
    /**
     * @param name the name to set
     */
    public void setName(String name) {
        this.name = name;
    }

    @Override
    public void printName() {
        System.out.println(this.getClass().getName() + ":" + this.name);

    }
}

3、七匹狼衣服

package com.test.demo;

/**
 *
 * @author test
 */
public class SeptwolvesClothes implements Clothes{

    private String name;
    public SeptwolvesClothes(String name) {
        this.name = name;
        System.out.println("create a SeptwolvesClothes.");
    }
    /**
     * @return the name
     */
    public String getName() {
        return name;
    }
    /**
     * @param name the name to set
     */
    public void setName(String name) {
        this.name = name;
    }

    @Override
    public void printName() {
        System.out.println(this.getClass().getName() + ":" + this.name);

    }
}

4、七匹狼裤子
package com.test.demo;

/**
 *
 * @author test
 */

public class SeptwolvesPants implements Pants{
    private String name;
    public SeptwolvesPants(String name) {
        this.name = name;
        System.out.println("create a SeptwolvesPants.");
    }
    /**
     * @return the name
     */
    public String getName() {
        return name;
    }
    /**
     * @param name the name to set
     */
    public void setName(String name) {
        this.name = name;
    }

    @Override
    public void printName() {
        System.out.println(this.getClass().getName() + ":" + this.name);

    }
}

3.抽象工厂

package com.test.demo;

/**
 *
 * @author test
 */

public interface SuitFactory {
    Clothes createClothes(String name);
    Pants createPants(String name);
}

4.具体工厂子类

1、花花公子工厂

package com.test.demo;

/**
 *
 * @author test
 */

public class PlayBoyFactory implements SuitFactory {

    @Override
    public Clothes createClothes(String name) {
        return new PlayBoyClothes(name);    }

    @Override
    public Pants createPants(String name) {
        return new PlayBoyPants(name);
    }
}

2、七匹狼工厂

package com.test.demo;

/**
 *
 * @author test
 */

public class SeptwolvesFactory implements SuitFactory {

    @Override
    public Clothes createClothes(String name) {
        return new SeptwolvesClothes(name);    }

    @Override
    public Pants createPants(String name) {
        return new SeptwolvesPants(name);
    }
}

最后,使用简单的测试类,来验证下 不同的工厂能够产生不同的产品对象:测试类如下:

package com.test.demo;

/**
 *
 * @author test
 */

public class Test {
    public static void main(String[] args) {
        SuitFactory PlayBoyFactory = new PlayBoyFactory();
        SuitFactory SeptwolvesFactory = new SeptwolvesFactory();

        Clothes playBoyClothes = PlayBoyFactory.createClothes("PlayBoy秋冬上装");
        Pants playBoyPants = PlayBoyFactory.createPants("PlayBoy秋冬裤子");

        Clothes septwolvesClothes = SeptwolvesFactory.createClothes("Septwolves秋冬上装");
        Pants septwolvesCants = SeptwolvesFactory.createPants("Septwolves秋冬裤子");

        playBoyClothes.printName();
        playBoyPants.printName();
        septwolvesClothes.printName();
        septwolvesCants.printName();
    }
}

打印结果如下:

create a PlayBoyClothes.
create a PlayBoyPants.
create a SeptwolvesClothes.
create a SeptwolvesPants.
com.test.demo.PlayBoyClothes:PlayBoy秋冬上装
com.test.demo.PlayBoyPants:PlayBoy秋冬裤子
com.test.demo.SeptwolvesClothes:Septwolves秋冬上装
com.test.demo.SeptwolvesPants:Septwolves秋冬裤子

总结

优点:当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。

缺点:产品族扩展非常困难,要增加一个系列的某一产品,既要在抽象的 Creator 里加代码,又要在具体的里面加代码。

参考文章

https://baike.baidu.com/item/%E6%8A%BD%E8%B1%A1%E5%B7%A5%E5%8E%82%E6%A8%A1%E5%BC%8F/2361182