在学习了厉风行老师的《设计模式系列课程》后为方便查看,对其内容进行整理:
一、什么是抽象工厂模式
抽象工厂模式是所有形态的工厂模式中最为抽象和最具一般性的。抽象工厂模式可以向客户端提供一个接口,使得客户端在不必
指定产品
的具体类型的情
况下,能够创
建多个产品族的产品对
象。
此处引入了一个新的概念产品族,那什么是产品族呢?百度一下:产品族是以产品平台为基础,通过添加不同的个性模块,以
满足不同客户个性化需求的一组相关产品。
图.产品族等级结构示意
果), Banana(香蕉),Pear(梨)这三种水果对应上图中的产品等级结构。
所谓产品族通俗来说即是:具有某一共性的一系列相关产品.以前面的Apple(苹果),Banana(香蕉),Pear(梨)为例,Apple(苹
这三种水果有产自南方的,也有产自北方的,北方和南方则对应上图中的产品族,产自北方的Apple(苹果),Banana(香
蕉),Pear(梨)
就构成一个产品族,它们的共性是产自北方,同样产自南方的Apple(苹果),Banana(香蕉),Pear(梨)也构成了一个产品族。
1.抽象工厂(Creator)角色 抽象工厂模式的核心,包含对多个产品结构的声明,任何工厂类都必须实现这个接口。 2.具体工厂(Concrete Creator)角色 具体工厂类是抽象工厂的一个实现,负责实例化某个产品族中的产品对象。 3.抽象(Product)角色 抽象模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口。 4.具体产品(Concrete Product)角色 抽象模式所创建的具体实例对象
总结:抽象工厂中的方法对应产品结构,具体工厂对应产品族。
接下来用代码进行说明:
保留之前工厂方法模式一章中的Fruit接口,用来负责描述所有水果实例应该共有的方法。
public interface Fruit { /* * 采集 */ public void get(); }
此时Apple(苹果)和Banana(香蕉)将不再是具体的产品类而是抽象类,因为它们还需要进一步划分北方和南方两个产品族。public abstract class Apple implements Fruit{ /* * 采集 */ public abstract void get(); }public abstract class Banana implements Fruit{ /* * 采集 */ public abstract void get(); }
再进一步细分,苹果(Apple)被具体化为北方苹果(NorthApple)和南方苹果(SouthApple)。public class NorthApple extends Apple { public void get() { System.out.println("采集北方苹果"); } }public class SouthApple extends Apple { public void get() { System.out.println("采集南方苹果"); } }
香蕉(Banana)被具体化为北方香蕉(NorthBanana)和南方香蕉(SouthBanana).public class NorthBanana extends Banana { public void get() { System.out.println("采集北方香蕉"); } }public class SouthBanana extends Banana { public void get() { System.out.println("采集南方香蕉"); } }继续写工厂,与之前的FruitFactory有所不同,此时的FruitFactory需为每一个产品结构添加获取方法声明。
public interface FruitFactory { //实例化Apple public Fruit getApple(); //实例化Banana public Fruit getBanana(); }
为每一个产品族添加相应的工厂,NorthFruitFactory负责生产所有北方的水果,SouthFruitFactory负责生产所有南方的水果。public class NorthFruitFactory implements FruitFactory { public Fruit getApple() { return new NorthApple(); } public Fruit getBanana() { return new NorthBanana(); } }public class SouthFruitFactory implements FruitFactory { public Fruit getApple() { return new SouthApple(); } public Fruit getBanana() { return new SouthBanana(); } }
创建MainClass类进行测试。public class MainClass { public static void main(String[] args) { FruitFactory ff3 = new WenshiFruitFactory(); Fruit apple3 = ff3.getApple(); apple3.get(); Fruit banana3 = ff3.getBanana(); banana3.get(); } }
运行打印: 采集北方苹果 采集北方香蕉 采集南方苹果 采集南方香蕉
三、抽象工厂模式的优缺点
优点:
1、抽象工厂模式隔离了具体类的生产,使得客户并不需要知道什么被创建。
2、当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。
3、增加新的具体工厂和产品族很方便,无须修改已有系统,符合“开闭原则”。
缺点:
增加新的产品等级结构很复杂,需要修改抽象工厂和所有的具体工厂类,对“开闭原则”的支持呈现倾斜性。
优点代码举例:需求更改需要增加温室产品组。
先增加温室苹果和温室香蕉两个类。
public class WenshiApple extends Apple { public void get() { System.out.println("采集温室苹果"); } }
public class WenshiBanana extends Banana { public void get() { System.out.println("采集温室香蕉"); } }
再增加生产温室水果的温室工厂。
public class WenshiFruitFactory implements FruitFactory { public Fruit getApple() { return new WenshiApple(); } public Fruit getBanana() { return new WenshiBanana(); } }
在MainClass中创建温室水果测试。
public class MainClass { public static void main(String[] args) { FruitFactory ff3 = new WenshiFruitFactory(); Fruit apple3 = ff3.getApple(); apple3.get(); Fruit banana3 = ff3.getBanana(); banana3.get(); } }
运行打印:
采集温室苹果
采集温室香蕉
产自温室的苹果和香蕉被正确创建,只是增加了新产品族的具体产品类和负责生产该产品族所有产品的工厂,无需对现有代码进行修改,很好的符合“开闭原则”。