设计模式之---工厂模式、建造者模式
作者:互联网
☺ 对于工厂模式,个人学习需要掌握
- 注意答案的重点标黑了。对于工厂模式、建造者模式,掌握,我下面这几点就很棒棒。
一、工厂模式
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
如果本文对你有帮助的话记得给一乐点个赞哦,感谢!
标签:void,建造,模式,工厂,---,Override,设计模式,public 来源: https://www.cnblogs.com/shan333/p/16355126.html