前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >设计模式 - 抽象工厂模式

设计模式 - 抽象工厂模式

作者头像
子乾建建-Jeff
发布2020-06-29 15:18:50
3500
发布2020-06-29 15:18:50
举报
文章被收录于专栏:iBroProiBroPro

预计阅读时间:10-14min

情景引入:

「得不到的永远在骚动,买不起的都是在装聋」

(某商场)

子乾:诶诶诶,这儿有一个 HW 体验店,你确定不进去看看嘛?

朱少:走走瞧瞧看,手机差不多换它一个。

子乾:你看这个,这个音响,我喜欢。

朱少:喜欢有屁用,有钱买吗?我有一个小M的,用着挺好。

子乾:我不,我偏买。我还要手机,俩品牌的都要。

朱少:到家再买。哥写代码挣钱再给你买。

(快用代码实现一下)

回顾工厂模式:

在工厂模式中,每一个工厂负责生产对应的一款具体的产品,具有唯一性。但有时候,人们还需要一个工厂能够提供多个产品对象。

比如上述情景,一个 HW 工厂可以提供手机和音响两个产品,而 XM 工厂也可以提供手机和音响两个产品。

当客户需要购买时,用代码模拟购买过程。

知识快充:

概念1:

产品等级结构:即产品的继承结构。比如一个抽象类(或接口)是手机,其有子类 HW手机、XM 手机。

概念2:

产品族:在抽象工厂模式中,产品族指由同一个工厂生产的位于不同产品等级结构的一组产品。比如 HW 生产的手机和音响。H 手机属于手机产品等级结构,H 音响属于手机产品等级结构。

上述情景引入中,要购买的不是一个产品,就要求工厂生产的具体产品不是一个简单的对象,而是多个位于不同产品等级结构、属于不同类型的具体产品。

应使用 抽象工厂模式

Abstrict Factory Pattern:

Provide an interface for creating families of related or dependent objects without specifying their concrete classes.

不太明白看下面:

提供一个创建一系列相关或相互依赖对象的接口,而无须指定他们具体的类。

抽象工厂模式是对象创建型模式,是所有形式的工厂模式中最为抽象和最具一般性的一种形式。

也可以这么理解,具体工厂负责创建一族产品。当某工厂可以生产出不同产品等级的一个产品族中的所有对象时,该模式更高效。

角色:

Factory :抽象工厂

ConcreteFactory :具体工厂

Product :产品

ConcreteProduct :具体产品

类图:

上述类图映射到代码中:

产品:抽象产品 + 具体产品的代码示例

代码语言:javascript
复制
// 抽象产品A
public interface AbstractProductA{
  public void methodA();
}

// 具体产品A1
public class ConcreteProductA1 implememts AbstractProductA{
  public void methodA(){
    // To do ...
  }
}

// 抽象产品B
public interface AbstractProductB{
  public void methodB();
}

// 具体产品B1
public class ConcreteProductB1 implememts AbstractProductB{
  public void methodB(){
    // To do ...
  }
}

工厂:抽象工厂 + 具体工厂

代码语言:javascript
复制
// 抽象工厂
public interface Factory{
  public AbstractProductA createProductA();
  public AbstractProductB createProductB();
}

// 1 号具体工厂
public class ConcreteFactory1 implements Factory{
  public AbstractProductA createProductA(){
      return new ConcreteProductA1();
  }
  
  public AbstractProductB createProductB(){
      return new ConcreteProductB1();
  }
}

客户端代码:

代码语言:javascript
复制
···
Factory factory;
AbstractProductA productA;
AbstractProductB productB;
factory = new ConcreteFactory1(); //实例 1 厂
productA = factory.createProductA(); // 1 厂生产 A 产品
productA.algorithmA();

productB = factoru.createProductB(); // 1 厂生产 B 产品
productB.algorithm();

回归到本例代码的解析,两个厂家,都可以生产手机和音响

类图:

首先抽象出两个产品,一个手机,一个音响;

然后画出他们具体的子类。

其次抽象出一个工厂,工厂可以生产两种产品,手机和音响;

然后有两个具体工厂,每一个工厂都可以生产这两种产品,手机和音响;

工厂和产品具有“生产、创建”的关系,具体产品依赖具体工厂。

最后,在客户端使用抽象类存储具体的对象,完美的里氏代换原则。

代码:

第一步:定义抽象产品,手机接口:

代码语言:javascript
复制
package com.sample.abstractfactorypattern.product;

public interface Phone {

    public void call();

}

第二步:实现该接口,HWPhone 和 XMPhone:

代码语言:javascript
复制
// HWPhone
package com.sample.abstractfactorypattern.product;

public class HWPhone implements Phone {
    @Override
    public void call() {
        System.out.println("正在使用 HWPhone ...");
    }
}

// XMPhone
package com.sample.abstractfactorypattern.product;

public class XMPhone implements Phone{

    @Override
    public void call() {
        System.out.println("正在使用 XMPhone 。。。");
    }
}

第三步:定义音响产品接口

代码语言:javascript
复制
package com.sample.abstractfactorypattern.product;

public interface Sound {
      public void play();
}

第四步:实现音响接口,定义 HWSound 类和 XMSound 类:

代码语言:javascript
复制
// HWSound
package com.sample.abstractfactorypattern.product;

public class HWSound implements Sound {
    @Override
    public void play() {
        System.out.println("已购买 HWSound 。。。");
    }
}

// XMSound
package com.sample.abstractfactorypattern.product;

public class XMSound implements Sound{

    @Override
    public void play() {
        System.out.println("已购买 XMSound... ");
    }
}

第五步:定义抽象工厂,它包含两个方法,因为有两个产品:

代码语言:javascript
复制
package com.sample.abstractfactorypattern.factory;

import com.sample.abstractfactorypattern.product.Phone;
import com.sample.abstractfactorypattern.product.Sound;

public interface Factory {

    public Phone createPhone();
    public Sound createSound();

}

第六步:实现抽象工厂,定义 HWFactory 和 XMFactory,此时返回的即产品对象,可表示 产品对象 被创建成功。

代码语言:javascript
复制
// HW 工厂
package com.sample.abstractfactorypattern.factory;

import com.sample.abstractfactorypattern.product.HWPhone;
import com.sample.abstractfactorypattern.product.HWSound;
import com.sample.abstractfactorypattern.product.Phone;
import com.sample.abstractfactorypattern.product.Sound;

public class HWFactory implements Factory {
    @Override
    public Phone createPhone() {
        return new HWPhone();
    }

    @Override
    public Sound createSound() {
        return new HWSound();
    }
}

// XM 工厂
package com.sample.abstractfactorypattern.factory;

import com.sample.abstractfactorypattern.product.Phone;
import com.sample.abstractfactorypattern.product.Sound;
import com.sample.abstractfactorypattern.product.XMPhone;
import com.sample.abstractfactorypattern.product.XMSound;

public class XMFactory implements Factory {
    @Override
    public Phone createPhone() {
        return new XMPhone();
    }

    @Override
    public Sound createSound() {
        return new XMSound();
    }
}

第七步:客户端调用实现

对象都存储在接口类型中,在下面动态进行赋值调用。

当在选定一个工厂时,就代表选择了该品牌产品;当选定哪一个工厂方法时,就代表选择了该方法下的具体产品。

省去了传入一个参数的烦扰,也可以防止参数输入错误,导致拿不到产品。

代码语言:javascript
复制
package com.sample.abstractfactorypattern;

import com.sample.abstractfactorypattern.factory.Factory;
import com.sample.abstractfactorypattern.factory.HWFactory;
import com.sample.abstractfactorypattern.factory.XMFactory;
import com.sample.abstractfactorypattern.product.Phone;
import com.sample.abstractfactorypattern.product.Sound;

public class Client {
    public static void main(String[] args){
        Factory factory;
        Phone phone;
        Sound sound;

        // 购买 HW 手机
        factory = new HWFactory();
        phone = factory.createPhone();
        phone.call();

        // 购买 XM 音响
        factory = new XMFactory();
        sound = factory.createSound();
        sound.play();

        // 购买 XM 手机
        phone = factory.createPhone();
        phone.call();

        // 购买 HW 音响
        factory = new HWFactory();
        sound = factory.createSound();
        sound.play();
    }
}

运行效果:

项目结构:

抽象工厂模式优点:

·隔离了具体类的生成

·当一个产品族的多个对象产品被设计成一起工作时,能保证客户端只使用同一个产品族中的对象。

·增加新的产品族比较方便,符合开闭原则。

抽象工厂模式缺点:

·增加新的产品等级结构比较麻烦,需要修改具体工厂、抽象工厂等,违背了开闭原则。

上述的优缺点也体现了抽象工厂模式下开闭原则的倾斜性:

增加新的产品族,符合开闭原则。比如,新增 PG 的手机和音响,那么只需在抽象产品接口下新增两个具体实现类,PGPhone 和 PGSound;同时,在新增一个具体工厂 PGFactory,实现抽象工厂。

而当新增产品等级结构时,不符合开闭原则。比如 HW 和 XM 两家工厂新增产品电脑。就需要新增一个抽象接口类 Computer,以及具体实现类;同时,工厂中,也需要对抽象工厂和具体工厂进行修改,增加 createComputer 方法。

模式的适用环境:

一个系统不依赖于产品类实例如何被创建、组合和表达的细节

系统中有多于一个的产品族,但每次只使用其中某一产品族

属于同一个产品族的产品将在一起使用,这一约束必须在系统的设计中体现出来

产品等级结构稳定,设计完成之后,不会向系统中增加新的产品等级结构或者删除已有的产品等级结构

好了,我的读者朋友们,今天对于抽象工厂模式的分解与分享就到此结束了。对于我文中列举的例子,我说明白了吗?您感觉怎么样?欢迎与我私下交流。

感谢阅读,感谢陪伴。

表情包来源网络,侵删。

原创不易

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-03-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 iBroPro 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档