您现在的位置是:首页 >其他 >设计模式详解(四)——抽象工厂模式网站首页其他
设计模式详解(四)——抽象工厂模式
抽象工厂模式简介
抽象工厂模式定义
抽象工厂模式是一种创建型设计模式,它提供了一种方法来创建一组相关或依赖的对象,而无需指定他们的具体类。
抽象工厂模式,也称为工厂的工厂,有一个工厂创建其他工厂。
当使用抽象工厂模式时,我们首先使用超级工厂创建工厂,然后使用创建的工厂创建对象。
在 Spring Boot 开发中,抽象工厂模式可以通过使用 @Autowired 和 @Qualifier 注解来实现。
产品族和产品等级:
产品族:一个品牌下面的所有产品;例如奥迪下面的商务型、MINI型称为华为的产品族;
产品等级:多个品牌下面的同种产品;例如奥迪和宝马下面的各种商务车型,称为一个产品等级;
抽象工厂模式的各个角色和工厂方法的如出一辙:
- 抽象工厂角色:这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的 父类。在java中它由抽象类或者接口来实现
- 具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。在java中它 由具体的类来实现
- 抽象产品角色:它是具体产品继承的父类或者是实现的接口。在java中一般有抽象类或者接口来实现
- 具体产品角色:具体工厂角色所创建的对象就是此角色的实例。在java中由具体的类来实现
应用场景:
提供一个产品类的工厂,所有的产品以同样的接口出现,使用者不依赖于具体的实现。
强调一些列相关的产品对象(如下面示例的产品族),一起使用创建对象需要大量重复的代码。
**结构:**抽象工厂、具体工厂;抽象产品、具体产品。
优缺点:
优点:获取具体系列产品只需要通过具体系列工厂获取,无序关心创建的细节;抽象工厂模式将具体产品的创建延迟到具体工厂的子类中,这样将对象的创建封装起来,可以减少客户端与具体产品类之间的依赖,从而使系统耦合度低,这样更有利于后期的维护和扩展
缺点:规定了所有可能被创建的产品集合,若是出现某一个系列出现新的产品就会导致所有的系列都会创建指定的接口!扩展新产品困难,增加了系统的抽象性与复杂度。抽象工厂模式将具体产品的创建延迟到具体工厂的子类中,这样将对象的创建封装起来,可以减少客户端与具体产品类之间的依赖,从而使系统耦合度低,这样更有利于后期的维护和扩展
下面举例:
有手机和手表两种产品,有华为和苹果两种品牌,两种品牌都可以生产手机和手表;
有手机和手表两种产品,定义两个接口;
华为和苹果都可以生产这两种产品,所以有4个实现类;
现在需要创建华为和苹果的工厂类,先将工厂类进行抽象,里面有创建两个产品的方法,返回的是产品的接口类;
创建华为和苹果的工厂实现类,继承工厂类接口,实现创建各自产品的方法;
客户端调用时,直接用工厂接口类创建需要的工厂,拿到对应的产品;
- 手机产品接口和手表产品接口
/**
* @author yyx
*/
public interface Phone {
//打电话
void call();
//发信息
void send();
}
/**
* @author yyx
*/
public interface Watch {
//打开
void open();
//关闭
void close();
}
- 华为和苹果的产品的4个实现类
/**
* @author yyx
*/
public class HuaweiPhone implements Phone {
@Override
public void call() {
System.out.println("华为手机打电话");
}
@Override
public void send() {
System.out.println("华为手机发信息");
}
}
/**
* @author yyx
*/
public class HuaweiWatch implements Watch {
@Override
public void open() {
System.out.println("华为手表打开");
}
@Override
public void close() {
System.out.println("华为手表关闭");
}
}
/**
* @author yyx
*/
public class ApplePhone implements Phone {
@Override
public void call() {
System.out.println("苹果手机打电话");
}
@Override
public void send() {
System.out.println("苹果手机发信息");
}
}
/**
* @author yyx
*/
public class AppleWatch implements Watch {
@Override
public void open() {
System.out.println("苹果手表打开");
}
@Override
public void close() {
System.out.println("苹果手表打开");
}
}
- 工厂接口类
/**
* @author yyx
*/
public interface Factory {
// 生产手机
Phone Phone();
// 生产手表
Watch watch();
}
- 华为和苹果工厂实现类,继承工厂接口
/**
* @author yyx
*/
public class HuaweiFactory implements Factory{
@Override
public Phone Phone() {
return new HuaweiPhone();
}
@Override
public Watch watch() {
return new HuaweiWatch();
}
}
/**
* @author yyx
*/
public class AppleFactory implements Factory {
@Override
public Phone Phone() {
return new ApplePhone();
}
@Override
public Watch watch() {
return new AppleWatch();
}
}
- 客户端,通过 IFactory 创建各自的工厂,通过工厂拿到对应的产品
/**
* @author yyx
*/
public class Client {
public static void main(String[] args) {
System.out.println("华为");
// 创建华为工厂
HuaweiFactory huaweiFactory = new HuaweiFactory();
// 生产华为手机
Phone huaweiPhone = huaweiFactory.Phone();
huaweiPhone.call();
huaweiPhone.send();
// 生产华为手表
Watch huaweiWatch = huaweiFactory.watch();
huaweiWatch.open();
huaweiWatch.close();
System.out.println("苹果");
// 创建华为工厂
AppleFactory appleFactory = new AppleFactory();
// 生产华为手机
Phone applePhone = appleFactory.Phone();
applePhone.call();
applePhone.send();
// 生产华为手表
Watch appleWatch = appleFactory.watch();
appleWatch.open();
appleWatch.close();
}
}
运行结果如下所示:
华为
华为手机打电话
华为手机发信息
华为手表打开
华为手表关闭
苹果
苹果手机打电话
苹果手机发信息
苹果手表打开
苹果手表打开
在以下情况下可以考虑使用抽象工厂模式:
- 一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节,这对于所有类型的工厂模式都是很重要的,用户无须关心对象的创建过程,将对象的创建和使用解耦。
- 系统中有多于一个的产品族,而每次只使用其中某一产品族。可以通过配置文件等方式来使得用户可以动态改变产品族,也可以很方便地增加新的产品族。
- 属于同一个产品族的产品将在一起使用,这一约束必须在系统的设计中体现出来。同一个产品族中的产品可以是没有任何关系的对象,但是它们都具有一些共同的约束,如同一操作系统下的按钮和文本框,按钮与文本框之间没有直接关系,但它们都是属于某一操作系统的,此时具有一个共同的约束条件:操作系统的类型。
- 产品等级结构稳定,设计完成之后,不会向系统中增加新的产品等级结构或者删除已有的产品等级结构。
总而言之:
抽象工厂模式:便于交换产品系列,同时让具体的创建实例过程与客户端分离,客户端是通过它们的抽象接口操纵实例,产品的具体类名也被具体工厂的实现分离,不会出现在客户端。
以上代码下载请点击该链接:https://github.com/Yarrow052/Java-package.git