镇楼
在某些书中使用了二维图说明抽象工厂模式。非常好,可是yqj2065不喜欢他们的产品族/产品等级,改成品牌/产品类型。
抽象工厂模式(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在后面考虑山寨问题)
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveXFqMjA2NQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" >
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除了生产配套的上衣、裤子外。还生产鞋子/Shoe。
IClothingFactory中须要加入
public Bottoms getShoe ();
Java8之前。接口不能升级。假设定义了接口。将接口送给客户程序猿使用,这时定义的接口就不能改动。由于在接口中加入一个方法,会导致老版本号接口的全部实现类的中断。
现在,在IClothingFactory广泛使用并且很须要与时俱进地加入getShoe()时。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有方法getShoe()。可是并不是事实上现类都给出有效的实现。你凭什么觉得IClothingFactory的实例都可以生产鞋子呢?
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveXFqMjA2NQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" >