首页 > 代码库 > 简明 抽象工厂模式(3.1)

简明 抽象工厂模式(3.1)


镇楼

抽象工厂模式(abstract factory pattern)较工厂方法模式强大之处,是一个工厂能够创建多个配套的产品。

日常生活中,抽象工厂模式比比皆是。例如服装厂可以生产配套的上衣/Tops、下装/Bottoms。电器公司如美的、海尔可以生产其品牌的冰箱、空调、电视机等。

抽象工厂模式的特点就是工厂接口中有两个以上的工厂方法

例程 2-6 品牌公司
package creational.factory.abstractFactory;
public class NikeFactory implements IClothingFactory{
    @Override public Tops getTops(){
        return new NikeTops();
    }
    @Override public Bottoms getBottoms(){
        return new NikeBottoms();
    }
}
抽象工厂模式概念简单,但是编写演示程序是至少要编写10个类(含Client)。如图所示。显然的,NikeFactory只会生产NikeTops和NikeBottoms,毕竟品牌公司不是山寨或贴牌公司。(yqj2065在后面考虑山寨问题)

package creational.factory.abstractFactory;
public class Client{
    public static void test(){
        IClothingFactory f =(IClothingFactory)tool.God.create("2-6-Factory");
        Tops tops = f.getTops();
        Bottoms bt =f.getBottoms();
        System.out.println(tops.getName());
        System.out.println(bt.getName() );
    }
}

抽象工厂模式包含4个角色。抽象工厂角色,如IClothingFactory;具体工厂角色,前者的子类型;抽象产品角色,如Tops和Bottoms;而具体产品角色,是抽象产品角色的子类型。

从Client的角度看,抽象工厂模式下,通过配置文件指定IClothingFactory,从而获得其生产的上衣/Tops,可以再指定其他的厂家,获得其生产裤子/Bottoms;Client仅仅依赖于抽象工厂角色和抽象产品角色;避免代码中的newNikeTops()和new AdidasBottoms。

2. 扩展性

IClothingFactory的子类,可以按照需要增添,符合OCP。

另一方面,假设现在的服装厂/IClothingFactory除了生产配套的上衣、裤子外,还生产鞋子/Show。IClothingFactory中需要添加

public Bottoms getShow ();

Java8之前,接口不能升级。如果定义了接口,将接口送给客户程序员使用,这时定义的接口就不能修改。因为在接口中添加一个方法,会导致老版本接口的所有实现类的中断。

如今,在IClothingFactory广泛使用而且非常需要与时俱进地添加getShow()时,Java8的默认方法(defender methods,Virtualextension methods)如同神奇的后悔药。
例程 2-7 默认方法
package creational.factory.abstractFactory;
public interface IClothingFactory{
    public Tops getTops();
    public Bottoms getBottoms();
    default public Shoe getShoe(){
        return null;
    }
}
class Client{
    public static void test(){
        IClothingFactory f =(IClothingFactory)tool.God.create("2-6-Factory-Nike");        
        //f =(IClothingFactory)tool.God.create("2-6-Factory-Ad");
        Shoe shoe =f.getShoe();
        System.out.println(shoe.getName() );
    }
}

NikeFactory改写了getShoe(),测试代码中Client可以正常获得Shoe对象;如果指定的具体工厂没有改写了getShoe(),则Shoe对象为null。

接口中添加默认方法,对于没有改写该默认方法的子类,都是一种退化继承——如同鸵鸟是鸟,违反LSP因而违反OCP。

接口中添加默认方法,保证以前的代码能够正常运行——因为以前的代码不可能知道也不存在使用getShoe(),因而保证了向前兼容。但是,编写新代码时就必须注意,IClothingFactory有方法getShow(),但是并非其实现类都给出有效的实现。你凭什么认为IClothingFactory的实例都能够生产鞋子呢?

简明 抽象工厂模式(3.1)