设计模式-抽象工厂模式
相关阅读:
继上一篇文章设计模式-工厂方法模式
我们发现在工厂方法模式中,每个工厂只能创建一类产品,为了解决这个问题,今天来学习一下抽象工厂模式
抽象工厂模式
提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类;具体的工厂负责实现具体的产品实例。
抽象工厂模式与工厂方法模式最大的区别:抽象工厂中每个工厂可以创建多种类的产品;而工厂方法每个工厂只能创建一类
模式中包含的角色及职责:
抽象产品族(AbstractProduct)角色:抽象产品的父类,用于描述抽象产品的公共接口
抽象产品(Product)角色:具体产品的父类 ,用于描述产品的公共接口
具体产品(Concrete Product)角色:抽象产品的子类,工厂类创建的目标类,即产品
抽象工厂(Creator)角色:具体工厂的父类,用于描述及具体工厂的公共接口
具体工厂(Concrete Creator)角色:抽象工厂的子类,被外界调用,用于实例化具体产品对象
使用方法:
1.创建抽象产品族类
2.创建抽象产品类,继承自抽象产品族类,定义具体产品的公共接口
3.创建具体产品类,继承自抽象产品类,定义生产的具体产品
4.创建抽象工厂类
5.创建具体工厂类,继承自抽象工厂类,定义创建对应具体产品的方法
6.外界调用具体工厂类,创建产品实例
实例:
实例代码已上传到GitLab,地址:https://gitlab.com/louisvv/DesignPattern
背景:客户来到了一个手机卖场,想要买手机,发现卖场里有苹果、三星手机专卖店,苹果手机有iphone X,iphone 8,三星手机有note 8,s9
目的:通过抽象工厂方法模式,实现手机的购买
流程:
整个流程如下:
客户要买手机 -> 客户问手机卖场(抽象工厂)有什么牌子的手机 -> 手机卖场说,有苹果和三星的专卖店(具体工厂类) -> 客户说我要买苹果手机 -> 创建苹果手机工厂 -> 到了苹果专卖店,店员问客户要哪个型号的手机,店里有iphone X和iphone 8 -> 客户说要iphone X -> 苹果手机工厂创建具体产品 Iphone X -> 客户买到了手机,心满意足的回家了
1.创建抽象产品族类:
创建手机类:
public interface Phone { public void show(); }
2.创建抽象产品类:
苹果手机类:
public abstract class ApplePhone implements Phone { }
三星手机类:
public abstract class SamsungPhone implements Phone{ }
3.创建具体产品类
苹果具体产品类:
Iphone X:
public class IphoneX extends ApplePhone { public void show() { System.out.println("Iphone X"); } }
Iphone 8:
public class Iphone8 extends ApplePhone { public void show() { System.out.println("Iphone 8"); } }
三星具体产品类:
Note8:
public class GalaxyNote8 extends SamsungPhone { public void show() { System.out.println("Galaxy Note 8"); } }
S9:
public class GalaxyS9 extends SamsungPhone { public void show() { System.out.println("Galaxy S9"); } }
4.创建抽象工厂类:
public interface AbstractFactory { public Phone getPhone(String phoneType) throws ClassNotFoundException, IllegalAccessException, InstantiationException; }
5.创建具体工厂类:
苹果手机工厂类:
public class AppleFactory implements AbstractFactory { public Phone getPhone(String phoneType) throws ClassNotFoundException, IllegalAccessException, InstantiationException { Class iphone=Class.forName(phoneType); return (ApplePhone) iphone.newInstance(); } }
三星手机工厂类:
public class SamsungFactory implements AbstractFactory { public Phone getPhone(String phoneType) throws ClassNotFoundException, IllegalAccessException, InstantiationException { //Class phone=Class.forName(phoneType); return (SamsungPhone)Class.forName(phoneType).newInstance(); } }
6.这里我们还需要一个工厂创建者,用来根据客户选择,创建对应的工厂
public class FactoryProducer { public static AbstractFactory getFactory(String factoryName) throws ClassNotFoundException, IllegalAccessException, InstantiationException { Class factory=Class.forName(factoryName); return (AppleFactory)factory.newInstance(); } }
7.外界调用具体工厂类:
public class Buyer { public static void main(String[] args) throws IllegalAccessException, InstantiationException, ClassNotFoundException { // 先问客户要什么牌子的手机,客户说要苹果的 // 创建苹果手机工厂 PhoneFactory appleFcatory = FactoryProducer.getFactory("AbstractFactory.AppleFactory"); System.out.println("客户想要买iphone X手机"); Phone iphoneX = appleFcatory.getPhone("AbstractFactory.IphoneX"); iphoneX.show(); System.out.println("客户想要买iphone 8手机"); Phone iphone8=appleFcatory.getPhone("AbstractFactory.Iphone8"); iphone8.show(); // 客户说要三星牌子的手机 // 创建三星手机工厂 PhoneFactory samsungFcatory = FactoryProducer.getFactory("AbstractFactory.SamsungFactory"); System.out.println("客户想要买s9手机"); Phone s9=samsungFcatory.getPhone("AbstractFactory.GalaxyS9"); s9.show(); System.out.println("客户想要买note 8手机"); Phone note8=samsungFcatory.getPhone("AbstractFactory.GalaxyNote8"); note8.show(); } }
结果:
客户想要买苹果iphone X手机 Iphone X 客户想要买苹果iphone 8手机 Iphone 8 客户想要买三星s9手机 Galaxy S9 客户想要买三星note 8手机 Galaxy Note 8
至此,实例演示完毕,我们总结一下抽象工厂模式的优缺点
优点:
1.更符合“开放-关闭”原则
2.符合单一职责原则
每个具体工厂类只负责创建对应的产品
3.降低耦合
抽象工厂模式将具体产品的创建延迟到具体工厂的子类中,这样将对象的创建封装起来,可以减少客户端与具体产品类之间的依赖,从而使系统耦合度低,这样更有利于后期的维护和扩展;
4.保证客户端始终只使用同一个产品族中的对象
5.相对于简单工厂,工厂方法模式,抽象工厂模式更加的抽象
缺点:
产品族扩展非常困难,这是因为抽象工厂接口中已经确定了可以被创建的产品集合,如果需要添加新产品,此时就必须去修改抽象工厂的接口,这样就涉及到抽象工厂类的以及所有子类的改变,这样也就违背了“开发——封闭”原则。
对于新的产品族符合开-闭原则
对于新的产品种类不符合“开-闭”原则,这一特性称为“开-闭”原则的倾斜性
应用场景:
了解其优缺点后,总结一下抽象工厂模式的应用场景:
- 一个系统不要求依赖产品类实例如何被创建、组合和表达的表达,这点也是所有工厂模式应用的前提
- 这个系统有多个系列产品,而系统中只消费其中某一系列产品
- 系统要求提供一个产品类的库,所有产品以同样的接口出现,客户端不需要依赖具体实现
举个例子:
比如游戏的装备和皮肤系统,就可以用抽象工厂方法模式,每次只能有一套皮肤和一件装备在指定位置上
亲,点个赞呗