☺ 对于工厂模式,个人学习需要掌握
- 注意答案的重点标黑了。对于工厂模式、建造者模式,掌握,我下面这几点就很棒棒。
一、工厂模式
1、什么是工厂模式:【关键字
factory
】答:创建对象时,不直接new,而是交由一个工厂类/工厂接口的
工厂方法
负责创建。2、工厂模式的意义
答:将实例化对象的代码提取出来,放到一个类(工厂类)中统一管理和维护;实现了创建者和调用者的分离,达到和主项目的依赖关系的解耦。从而提高项目的扩展和维护性。
3、工厂模式包括哪三种
答:简单工厂模式、工厂方法模式、抽象工厂模式
4、工厂模式的使用对比[简单工厂模式和工厂方法模式对比]:
答:简单工厂模式:虽然某种程度上不符合设计原则,但实际使用最多;工厂方法模式:不修改已有类的前提下,通过增加新的工厂类实现扩展;抽象工厂模式:不可以增加产品,可以增加产品族。
★ 虽然简单工厂模式不符合理论中的开闭原则,但是工厂方法模式定义的大量子类工厂实现类,管理也非常麻烦,
实际开发中使用的最多是简单工厂模式
.5、抽象工厂是什么
答:是工厂的工厂,超级工厂。适合生产一个稳定的产品族,采用
抽象工厂模式不需要关心构建过程,只关心什么产品由什么工厂生产即可
。6、工厂模式的应用场景:
- jdk中calendar的getInstance方法----简单工厂模式
- JDBC中的Connection对象的获取
- Spring中的IOC容器创建管理bean对象
- 反射中Class对象的newInstance方法
二、建造者模式
1、什么是建造者模式:【关键字
builder
】答:又叫生成器模式,是一种对象构建模式。将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
2、四种角色是什么
答:
(1) Product(产品角色):一个具体的产品对象。
(2) Builder(抽象建造者): 创建一个产品对象的各个部件的
接口/抽象类
。(3) ConcreteBuilder(具体建造者): 实现或继承抽象建造者接口,具体地构建和装配各个部件。
(4) Director(指挥者): 构建一个使用Builder接口的对象。它主要是用于创建一个复杂的对象。负责指挥构建一个工程,决定了工程如何构建,按照什么顺序构建。
举例:建造房子:
需要建房子:这一过程为打桩、砌墙、封顶。不管是普通房子也好,别墅也好都 需要经历这些过程,下面我们使用建造者模式(Builder Pattern)来完成.
1、产品角色:Product-房子,定义了房子的属性
2、
抽象建造者
:Builder-抽象的工人,定义了一些建造房子组件的方法和接口3、
具体建造者
:ConcreteBuilder-具体的工人,实现了建造房子组件4、
指挥者:Director-房子的指挥设计者,:负责指挥构建一个工程,决定了工程如何构建,按照什么顺序构建
3、建造者模式在JDK的应用和源码分析 (java.lang.StringBuilder中的建造者模式)
答:源码中建造者模式角色分析:
(1) Appendable接口,是抽象建造者, 定义了抽象方法,定义了多个append方法(抽象方法)
(2) AbstractStringBuilder抽象类,实现了 Appendable接口方法,AbstractStringBuilder 是建造者,只是不能实例化
(3)StringBuilder 继承了AbstractStringBuilder,即充当了指挥者角色,同时充当了具体的建造者,建造方法的实现是由 AbstractStringBuilder 完成, 而StringBuilder 继承了 AbstractStringBuilder
4、建造者模式的优缺点:
答:优点:(1) 产品的建造和表示分离,实现了解耦。使用建造者模式可以使客户端不必知道产品内部组成的细节;
(2) 用户使用不同的具体建造者即可得到不同的产品对象;
(3) 增加新的具体建造者无需修改原有类库代码,符合“开闭原则”
缺点:
建造者模式所创建的产品一般具有较多的共同点,其组成部分相似;如果产品之间的差异性很大,则不适合使用建造者模式
5、抽象工厂模式VS建造者模式
答:抽象工厂模式实现对产品家族的创建,一个产品家族是这样的一系列产品,采用
抽象工厂模式不需要关心构建过程,只关心什么产品 由什么工厂生产即可
。而建造者模式则是要求按照指定的蓝图建造产品
,它的主要目的是通过组装零配件而产生一个新产品。
一、工厂设计模式
1、作用和意义:实现了创建者和调用者的分离
。
★ 工厂模式的意义:将实例化对象的代码提取出来,放到一个类(工厂类)中统一管理和维护
,达到和主项目的依赖关系的解耦。从而提高项目的扩展和维护性。
2、三种工厂模式:
简单工厂模式、工厂方法模式、抽象工厂模式
3、 设计模式的依赖抽象原则:
创建对象实例时,不要直接 new 类, 而是把这个new 类的动作放在一个工厂的方法中,并返回。
不要让类继承具体类,而是继承抽象类或者是实现interface(接口)
不要覆盖基类中已经实现的方法
4、核心本质:
实例化对象不使用new,用工厂方法代替 factory
将选择实现类,创建对象统一管理和控制。从而将调用者跟我们的实现类解耦
■ 简单工厂模式(静态工厂模式)
用来生产同一等级结构中的任意产品(对于增加新的产品,需要扩展已有代码)
★ 对于简单工厂模式的举例:消费者买车
情况一:在没有使用简单工厂模式下,消费者(Consumer类)要买车,需要自己 new来构建一辆自己想要买的车。【
需要消费者自己制作车
(new 构建 车对象),则消费者是需要车的内部细节,才能new出车对象】情况二:使用简单工厂模式下,消费者只需要调用汽车工厂(CarFactory类)的获取车的方法,就可以买车了,不用关系车的创建的各种细节。而汽车工厂(CarFactory类)作用就是来制作车 (new 构建 车对象)的,并为外界提供获取车对象的方法。
public class Consumer { public static void main(String[] args) { // 1、没有使用简单工厂模式的情况: // Car car = new WuLing(); // Car car1 = new Tesla(); // 2、使用工厂创建 Car car = CarFactory.getCar("wuling"); Car car1 = CarFactory.getCar("tesila"); car.name(); car1.name(); } } public interface Car { void name(); } public class WuLing implements Car{ @Override public void name() { System.out.println("五菱宏光"); } } public class Tesla implements Car{ @Override public void name() { System.out.println("特斯拉"); } } // 静态工厂模式 // 开闭原则 public class CarFactory { // 方法一: 不满足开闭原则 public static Car getCar(String car){ if(car.equals("wuling")){ return new WuLing(); }else if(car.equals("tesila")){ return new Tesla(); }else { return null; } } // 方法二: public static Car geyWuling(){ return new WuLing(); } public static Car geyTesla(){ return new Tesla(); } }
□ 弊端:增加一个新的产品,做不到不修改代码。
例如:扩展一个大众的汽车,则需要修改工厂类(CarFactory)的Car(String car)方法的代码,不符合开闭原则【对扩展开发,对修改关闭】。
- 解决:工厂方法模式
■ 工厂方法模式:
用来生产同一等级结构中的固定产品(支持增加任意产品)
public class Consumer { public static void main(String[] args) { Car car = new WulingFactory().getCar(); Car car1 = new TeslaFactory().getCar(); car.name(); car1.name(); Car car2 = new MoBaiFactory().getCar(); car2.name(); } } public interface Car { void name(); } public class WuLing implements Car { @Override public void name() { System.out.println("五菱宏光"); } } public class Tesla implements Car { @Override public void name() { System.out.println("特斯拉"); } } // 工厂方法模式 public interface CarFactory { Car getCar(); } public class WulingFactory implements CarFactory{ @Override public Car getCar() { return new WuLing(); } } public class TeslaFactory implements CarFactory{ @Override public Car getCar() { return new Tesla(); } }
■ 工厂方法模式:通过将简单工厂模式原先的工厂类抽象成接口,然后根据车的种类,决定了抽象工厂接口的子类工厂实现类,并在子类工厂实现类内创建对应车种类的对象。
- 举例:现在多了一个车的品牌,叫宝马,相应的车工厂就有宝马工厂(实现工厂接口),在宝马车工厂实现了制作宝马车的方法。
3、理论和实际应用对比【对比简单工厂模式和工厂方法模式】
1、结构复杂度:simple>method
2、代码复杂度:simple>method
3、编程复杂度:simple>method
4、管理上的复杂度:simple>method
★ 虽然简单工厂模式不符合理论中的开闭原则,但是工厂方法模式定义的大量子类工厂实现类,管理也非常麻烦,
实际开发中使用的最多是简单工厂模式
4、抽象工厂模式:"工厂的工厂,超级工厂。适合生产一个稳定的产品族"
围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂
(1) 定义:
抽象工厂模式提供了一个创建一系列相关或者相互依赖对象的接口,无需指定他们的具体的类(针对整个产品族,产品等级数量相对固定的产品族)
(2) 适用场景:
- 客户端(应用层)不依赖于产品类实例如何被创建、实现等细节
- 强调一系列相关的产品对象(属于同一产品族)一起使用创建对象需要大量的重复代码
- 提供一个产品类的库,所有的产品以同样的接口出现,从而使得客户端不依赖于具体实现
■ 抽象工厂模式-其实就是工厂方法模式的抽象,体现在将原先的工厂定义为超级工厂接口,且包含的属性成员也是接口。
1、定义一个超级工厂接口IProductFactory:包含两个产品接口(接口属性成员)-手机产品接口IphoneProduct、路由器产品接口IRouterProduct 【产品族】
2、然后超级工厂接口有具体的实现子类-小米工厂XiaomiFactory、华为工厂HuaweiFactory
3、对于超级工厂接口定义的接口属性成员有对应的实现子类
- 然后手机产品接口IphoneProduct有具体的实现子类-小米手机实现子类XiaomiPhone、华为手机实现子类HuaweiPhone
- 同样路由器产品接口IRouterProduct 也有具体的实现子类-小米路由实现子类XiaomiRouter、华为路由实现子类HuaweiRouter
// 手机产品接口 public interface IphoneProduct { void start(); void shutdown(); void callup(); void sendSMS(); } // 小米手机 public class XiaomiPhone implements IphoneProduct{ @Override public void start() { System.out.println("开启小米手机"); } @Override public void shutdown() { System.out.println("关闭小米手机"); } @Override public void callup() { System.out.println("小米手机打电话"); } @Override public void sendSMS() { System.out.println("小米手机发短信"); } } // 华为手机 public class HuaweiPhone implements IphoneProduct{ @Override public void start() { System.out.println("开启华为手机"); } @Override public void shutdown() { System.out.println("关闭华为手机"); } @Override public void callup() { System.out.println("华为手机打电话"); } @Override public void sendSMS() { System.out.println("华为手机发短信"); } } // 路由器产品接口 public interface IRouterProduct { void start(); void shutdown(); void openWifi(); void setting(); } // 小米路由器 public class XiaomiRouter implements IRouterProduct{ @Override public void start() { System.out.println("启动小米路由器"); } @Override public void shutdown() { System.out.println("关闭小米路由器"); } @Override public void openWifi() { System.out.println("打开小米Wi-Fi"); } @Override public void setting() { System.out.println("小米设置"); } } // 华为路由器 public class HuaweiRouter implements IRouterProduct{ @Override public void start() { System.out.println("启动华为路由器"); } @Override public void shutdown() { System.out.println("关闭华为路由器"); } @Override public void openWifi() { System.out.println("打开华为Wi-Fi"); } @Override public void setting() { System.out.println("华为设置"); } } // 抽象产品工厂 public interface IProductFactory { // 生产手机 IphoneProduct iphoneProduct(); // 生产路由器 IRouterProduct irouterProduct(); } public class XiaomiFactory implements IProductFactory{ @Override public IphoneProduct iphoneProduct() { return new XiaomiPhone(); } @Override public IRouterProduct irouterProduct() { return new XiaomiRouter(); } } public class HuaweiFactory implements IProductFactory{ @Override public IphoneProduct iphoneProduct() { return new HuaweiPhone(); } @Override public IRouterProduct irouterProduct() { return new HuaweiRouter(); } } public class Client { public static void main(String[] args) { System.out.println("小米系列产品--------------------"); // 小米工厂 XiaomiFactory xiaomiFactory = new XiaomiFactory(); IphoneProduct iphoneProduct = xiaomiFactory.iphoneProduct(); iphoneProduct.callup(); iphoneProduct.sendSMS(); IRouterProduct iRouterProduct = xiaomiFactory.irouterProduct(); iRouterProduct.openWifi(); System.out.println("华为系列产品--------------------"); // 小米工厂 HuaweiFactory huaweiFactory = new HuaweiFactory(); iphoneProduct = huaweiFactory.iphoneProduct(); iphoneProduct.callup(); iphoneProduct.sendSMS(); iRouterProduct = huaweiFactory.irouterProduct(); iRouterProduct.openWifi(); } }
(3) 抽象工厂模式优缺点:
优点
- 具体产品在应用层的代码隔离,无需关心创建的细节
- 将一个系列的产品统一到一起创建
缺点:
规定了所有可能被创建的产品集合,产品族中扩展新的产品困难
;- 增加了系统的抽象性和理解难度
5、工厂模式小结:
- 简单工厂模式:虽然某种程度上不符合设计原则,但实际使用最多
- 工厂方法模式:不修改已有类的前提下,通过增加新的工厂类实现扩展
- 抽象工厂模式:不可以增加产品,可以增加产品族
6、工厂模式的应用场景:
- jdk中calendar的getInstance方法----简单工厂模式
- JDBC中的Connection对象的获取
- Spring中的IOC容器创建管理bean对象
- 反射中Class对象的newInstance方法
二、建造者模式
它提供了一种创建对象的最佳方式
1、定义:
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
建造者模式(Builder Pattern) 又叫生成器模式,是一种对象构建模式。它可以将复杂对象的建造过程抽象出来(抽象类别),使这个抽象过程的不同实现方法可以构造出不同表现(属性)的对象。
2、主要作用:
在用户不知道 对象的建造过程和细节的情况下就可以直接创建复杂的对象。
用户只需要给出指定复杂对象的类型和内容,建造者牧师负责按顺序创建复杂对象(把内部的建造过程和细节隐藏起来)
3、四种角色[★ 结合第四点的建造房子理解]
1) Product(产品角色):一个具体的产品对象。
2) Builder(抽象建造者): 创建一个Product对象的各个部件指定的 接口/抽象类
。
3) ConcreteBuilder(具体建造者): 实现接口,构建和装配各个部件。
4) Director(指挥者): 构建一个使用Builder接口的对象。它主要是用于创建一个复杂的对象。
它主要有两个作用,一是:隔离了客户与对象的生产过程,二是:负责控制产品对象的生产过程。
4、举例:建造房子
需要建房子:这一过程为打桩、砌墙、封顶。不管是普通房子也好,别墅也好都 需要经历这些过程,下面我们使用建造者模式(Builder Pattern)来完成.
1、产品角色:Product-房子,定义了房子的属性
2、
抽象建造者
:Builder-抽象的工人,定义了一些建造房子组件的方法和接口3、
具体建造者
:ConcreteBuilder-具体的工人,实现了建造房子组件4、
指挥者:Director-房子的指挥设计者,:核心负责指挥构建一个工程,决定了工程如何构建,按照什么顺序构建
// 产品:房子[定义了房子的属性] public class Product { private String buildA; private String buildB; private String buildC; private String buildD; public String getBuildA() { return buildA; } public void setBuildA(String buildA) { this.buildA = buildA; } public String getBuildB() { return buildB; } public void setBuildB(String buildB) { this.buildB = buildB; } public String getBuildC() { return buildC; } public void setBuildC(String buildC) { this.buildC = buildC; } public String getBuildD() { return buildD; } public void setBuildD(String buildD) { this.buildD = buildD; } @Override public String toString() { return "Product{" + "buildA='" + buildA + '\'' + ", buildB='" + buildB + '\'' + ", buildC='" + buildC + '\'' + ", buildD='" + buildD + '\'' + '}'; } } // 抽象的建造者[抽象的工人]:只是定义一些方法和接口 public abstract class Builder { abstract void buildA(); // 地基 abstract void buildB(); // 钢筋工程 abstract void buildC(); // 铺电线 abstract void buildD(); // 粉刷 // 完工:得到产品 abstract Product getProduct(); } // 具体的建造者[工人]: public class Worker extends Builder { private Product product; public Worker() { product = new Product();// 工人负责创建产品 } @Override void buildA() { product.setBuildA("地基"); System.out.println("地基"); } @Override void buildB() { product.setBuildB("钢筋工程"); System.out.println("钢筋工程"); } @Override void buildC() { product.setBuildC("铺电线"); System.out.println("铺电线"); } @Override void buildD() { product.setBuildD("粉刷"); System.out.println("粉刷"); } @Override Product getProduct() { return product; } } // 指挥者:核心负责指挥构建一个工程,工程如何构建,按照什么顺序构建,由他决定 public class Director { // 指挥工人按照顺序建房子 public Product build(Builder builder){ builder.buildA(); builder.buildB(); builder.buildC(); builder.buildD(); return builder.getProduct(); } } public class Test { public static void main(String[] args) { // 指挥 Director director = new Director(); // 指挥 具体的工人 完成产品 Product build = director.build(new Worker()); System.out.println(build.toString()); } }
5、建造者模式在JDK的应用和源码分析 (java.lang.StringBuilder中的建造者模式)
■ 源码中建造者模式角色分析
Appendable接口,是抽象建造者, 定义了抽象方法,定义了多个append方法(抽象方法)
AbstractStringBuilder抽象类,实现了 Appendable接口方法,AbstractStringBuilder 是建造者,只是不能实例化
StringBuilder 继承了AbstractStringBuilder,即充当了指挥者角色,同时充当了具体的建造者,建造方法的实现是由 AbstractStringBuilder 完成, 而StringBuilder 继承了 AbstractStringBuilder
6、建造者模式的优缺点
优点:
- 产品的建造和表示分离,实现了解耦。使用建造者模式可以使客户端不必知道产品内部组成的细节
- 用户使用不同的具体建造者即可得到不同的产品对象
- 将复杂产品的创建步骤分解在不同的方法中,是得创建过程更加清晰
- 具体的建造者之间是相互独立的,这有利于系统的扩展。增加新的具体建造者无需修改原有类库代码,符合“开闭原则”
缺点:
建造者模式所创建的产品一般具有较多的共同点,其组成部分相似;如果产品之间的差异性很大,则不适合使用建造者模式
,因此其使用范围受到一定的限制- 如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变的很庞大
7、抽象工厂模式VS建造者模式
抽象工厂模式实现对产品家族的创建,一个产品家族是这样的一系列产品:具有不同分类维度的产品组合,采用抽象工厂模式不需要关心构建过程,只关心什么产品 由什么工厂生产即可
。
而建造者模式则是要求按照指定的蓝图建造产品
,它的主要目的是通过组装零配件而产生一个新产品。
参考内容来源:《尚硅谷Java设计模式(图解+框架源码剖析)》 https://www.bilibili.com/video/BV1G4411c7N4
《【狂神说Java】通俗易懂的23种设计模式教学(停更)》https://www.bilibili.com/video/BV1mc411h719?p=5
如果本文对你有帮助的话记得给一乐点个赞哦,感谢!