【设计模式系列】(二) 工厂模式

【设计模式系列】(二) 工厂模式

问题描述

需求:现在要设计一个鸡店点餐系统。先设计一个鸡类(Chicken)、在设计两个子类黄焖鸡【YellowChicken】以及大盘鸡【BigChicken】、在设计一个鸡店类【ChickenStore】具有点鸡功能。

原型图如下:
在这里插入图片描述
实现代码如下:

  • Chicken

public abstract class Chicken {

    public abstract String getName();

    public void addSolt(){
        System.out.println("加糖");
    }

    public void addSugar(){
        System.out.println("加盐");
    }

    public void addMoney(){
        System.out.println("得加钱");
    }

}
  • BigChicken
public class BigChicken extends Chicken{
    @Override
    public String getName() {
        return "大盘鸡";
    }
}
  • YellowChicken
public class YellowChicken extends Chicken{
    @Override
    public String getName() {
        return "黄焖鸡";
    }
}

假如我们要去更换对象、就需要去重新去进行new、这显然违背了软件设计的开闭原则。如果我们使用工厂来生产对象、就和工厂打交道就可以了、彻底和对象进行解耦、更换对象在工厂里更换对象即可、达到和对象解耦的目的。

按照实际的业务划分、工厂模式分为三种:简单工厂模式、工厂方法模式、抽象工厂模式。

简单工厂模式

概述

简单工厂不是一种设计模式、一般我们把创建对象的叫做产品、创建产品的对象叫做工厂、如果只是创建的产品不多、只需要一个工厂类即可完成、叫做简单狗工厂模式。
在简单工厂模式中创建实例的方法通常为静态方法、因此简单工厂模式又称为静态工厂模式(Static Factory Method Pattern)
需要注意:简单工厂模式不属于23中设计模式之列。

结构

在这里插入图片描述
具体实现流程:先去创建Product接口、在去创建 ShowProductA、ShowProductB类去实现 Product 接口、通过 SimpleFactory 来去调用产品的实现。

  • Product
public interface Product {
    // 秀产品
    public void show();

}
  • ShowProductA
public class ShowProductA implements Product{
    @Override
    public void show() {
        System.out.println("我是A");
    }
}
  • SimpleFactory
/**
 * @ClassName: SimpleFactory
 * @Author: VV
 * @Version: 1.0.0
 * @Description: TODO
 * @MyEmail: vv1213418894@163.com
 * @CreateTime: 2022-08-26 15:01:41
 */
public abstract class SimpleFactory implements Product {

    public static Product showProduct(String name){
        if(name.equals("A")){
            return new ShowProductA();
        }else if(name.equals("B")){
            return new ShowProductB();
        }else{
            throw new RuntimeException("没有当前产品");
        }

    }

}

现在在以改进后的鸡店为例、进行讲解。
在这里插入图片描述

  • Chicken
 public abstract class Chicken {

    public abstract String getName();

    public void addSolt(){
        System.out.println("加糖");
    }

    public void addSugar(){
        System.out.println("加盐");
    }

    public void addMoney(){
        System.out.println("得加钱");
    }

}
  • BigChicken
public class BigChicken extends Chicken{
    @Override
    public String getName() {
        return "大盘鸡";
    }
}
  • YellowChicken
public class YellowChicken extends Chicken{
    @Override
    public String getName() {
        return "黄焖鸡";
    }
}
  • SimpleChickenFactory
public class SimpleChickenFactory {

    /**
     * 生成 chicken 类
     * @param type
     * @return 返回完成的 Chicken
     */
    public Chicken orderChicken(String type){
        Chicken chicken = null;
        if(type.equals("YellowChicken")){
            chicken = new YellowChicken();
        }else if(type.equals("BigChicken")){
            chicken = new BigChicken();
        }else {
            throw new RuntimeException("对不起、此鸡不在服务范围之内... ");
        }
        return chicken;
    }

}
  • ChickenStore
/**
 * @ClassName: ChickenStore
 * @Author: VV
 * @Version: 1.0.0
 * @Description: TODO
 * @MyEmail: vv1213418894@163.com
 * @CreateTime: 2022-08-26 15:28:28
 */
public class ChickenStore {

    public Chicken orderChicken(String type){
        // 从简单鸡厂获取鸡
        SimpleChickenFactory simpleChickenFactory = new SimpleChickenFactory();
        // 生产鸡
        Chicken chicken = simpleChickenFactory.orderChicken(type);
        // 自己加料
        chicken.addSugar();
        chicken.addSolt();
        chicken.addMoney();
        // 返回
        return chicken;
    }

}

后期要去点鸡、只要去 SimpleChickenFactory 去点鸡就行、但是产生了新的耦合、ChickenStore 与 SimpleChickenFactory 的耦合、工厂与产品的耦合。如果要去添加新的鸡种类、必定需要修改工厂、违法了开闭原则。

优缺点

优点:

  • 工厂类包含必要的逻辑判断,可以决定在什么时候创建哪一个产品的实例。客户端可以免除直接创建产品对象的职责,很方便的创建出相应的产品。工厂和产品的职责区分明确。
  • 客户端无需知道所创建具体产品的类名,只需知道参数即可。
    缺点:
  • 简单工厂模式的工厂类单一,负责所有产品的创建,职责过重,一旦异常,整个系统将受影响。且工厂类代码会非常臃肿,违背高聚合原则。
  • 使用简单工厂模式会增加系统中类的个数(引入新的工厂类),增加系统的复杂度和理解难度。
  • 系统扩展困难,一旦增加新产品不得不修改工厂逻辑,在产品类型较多时,可能造成逻辑过于复杂。
  • 简单工厂模式使用了 static 工厂方法,造成工厂角色无法形成基于继承的等级结构。
  • 增加新产品时还是需要修改工厂类的代码,违背了“开闭原则”。

工厂方法模式

概述

针对工厂模式的缺点(引入新产品、必须修改工厂类代码、违反开闭原则),使用工厂模式就可以解决问题、可以在不修改原来代码的情况下引进新的产品。

结构

1、抽象工厂:提供了创建产品的接口、调用者访问具体工厂产品的创建。
2、具体工厂:实现抽象工厂方法、完成具体产品的创建。
3、抽象产品:定义了产品的规范、描述产品主要特性及功能
4、具体产品:实现了抽象产品所定义的方法、由具体工厂来创建。
在这里插入图片描述

  • Product
public abstract class Product {

    public abstract void show();

}
  • ShowProductA
public class ShowProductA extends Product{
    @Override
    public void show() {
        System.out.println("产品A");
    }
}
  • ShowProductB
public class ShowProductB extends Product{
    @Override
    public void show() {
        System.out.println("产品B");
    }
}
  • SimpleFactory
public interface SimpleFactory {

    public Product createProduct();

}
  • SimpleFactoryA
public class SimpleFactoryA implements SimpleFactory{
    @Override
    public Product createProduct() {
        return new ShowProductA();
    }
}
  • SimpleFactoryB
public class SimpleFactoryB implements SimpleFactory{
    @Override
    public Product createProduct() {
        return new ShowProductB();
    }
}
  • Client
/**
 * @ClassName: Client
 * @Author: VV
 * @Version: 1.0.0
 * @Description: TODO
 * @MyEmail: vv1213418894@163.com
 * @CreateTime: 2022-08-26 16:28:32
 */
public class Client {

    public static void main(String[] args) {
        // A 工厂生产 A 产品
        SimpleFactory simpleFactoryA = new SimpleFactoryA();
        Product product = simpleFactoryA.createProduct();
        // B 工厂生产 B 产品
        SimpleFactoryB simpleFactoryB = new SimpleFactoryB();
        Product product1 = simpleFactoryB.createProduct();
        // 开始秀
        product.show();
        product1.show();
    }

}

现在在以改进后的鸡店为例、进行讲解。(画了半天、还是GG了)
在这里插入图片描述

  • Chicken
public abstract class Chicken extends Client {

    public abstract String getName();

    public void addSolt(){
        System.out.println("加盐");
    }

    public void addSugar(){
        System.out.println("加糖");
    }

    public void addMoney(){
        System.out.println("加钱");
    }

}
  • BigChicken
public class BigChicken extends Chicken{
    @Override
    public String getName() {
        return "大盘鸡";
    }
}

  • YellowChicken
public class YellowChicken extends Chicken{
    @Override
    public String getName() {
        return "黄焖鸡";
    }
}
  • ChickenFactory
public interface ChickenFactory {

    public Chicken createChicken();

}
  • BigChickenFactory
public class BigChickenFactory implements ChickenFactory{
    @Override
    public Chicken createChicken() {
        return new BigChicken();
    }
}

  • YellowChickenFactory
public class YellowChickenFactory implements ChickenFactory{
    @Override
    public Chicken createChicken() {
        return new YellowChicken();
    }
}
  • Client
public class Client {

    public static void main(String[] args) {
        // 开始创建产品、大盘鸡
        BigChickenFactory bigChickenFactory = new BigChickenFactory();
        Chicken chicken = bigChickenFactory.createChicken();
        chicken.getName();

        // 黄焖鸡
        YellowChickenFactory yellowChickenFactory = new YellowChickenFactory();
        Chicken chicken1 = yellowChickenFactory.createChicken();
        chicken1.getName();

    }

}

优点:

  • 用户只需要知道工厂名称即可、无需知道产品的创建过程。
  • 灵活性增强、对于新产品、只需要多写一个相应的工厂类。
  • 典型的解耦框架、高层模块只需要知道产品的抽象类、无需关系其他实现类、满足迪米特法则、依赖倒置原则和里氏替换原则。

缺点:

  • 类的个数容易过多、增加复杂度。
  • 增加系统抽象性和理解难度
  • 工厂模式只能生产一种产品、可以使用抽象工厂模式解决。

抽象工厂

概述

前面介绍这么多、都是去生产跟鸡相关的产品、但是现实生活中也不能天天去吃鸡、得换换口味、比如鸭、牛、猪等。但是鸡场只能产鸡、想要吃其他就要开其他厂子。

这些工厂只生产同种类产品,同种类产品称为同等级产品,也就是说:工厂方法模式只考虑生产同等级的产品,但是在现实生活中许多工厂是综合型的工厂,能生产多等级(种类) 的产品,如电器厂既生产电视机又生产洗衣机或空调,大学既有软件专业又有生物专业等。

接下来介绍的是抽象工厂模式、将要考虑多等级多产品的生产。
在这里插入图片描述

结构

抽象工厂有以下几个角色:

  • 抽象工厂:提供了创建产品的接口、包含多个创建产品的方法、可以创建多个不同等级的产品。
  • 具体工厂:主要实现抽线工厂的多个抽象方法、完成具体产品的创建。
  • 抽象产品:定义了产品的规范、描述了产品的主要特性和功能、抽象工厂有多个抽象产品。
  • 具体产能:实现了抽象产品角色定义的接口、由具体工厂来创建、它同具体工厂是一对多的关系。
    在这里插入图片描述
  • ProductA
public abstract class ProductA {

    public abstract void show();

}
  • ProductB
public abstract class ProductB {

    public abstract void show();

}
  • ShowProductA1
public class ShowProductA1 extends ProductA{
    @Override
    public void show() {
        System.out.println("这是 A 系列 1 号产品");
    }
}
  • ShowProductA2
public class ShowProductA2 extends ProductA{
    @Override
    public void show() {
        System.out.println("这是 A 系列 2 号产品");
    }
}
  • ShowProductB1
public class ShowProductB1 extends ProductB{
    @Override
    public void show() {
        System.out.println("这是 B 系列 1 号产品");
    }
}
  • ShowProductB2
public class ShowProductB2 extends ProductB{
    @Override
    public void show() {
        System.out.println("这是 B 系列 2 号产品");
    }
}
  • ProductFactory
public interface ProductFactory {

    public ProductA createProductA();

    public ProductB createProductB();

}
  • Factory01
public class Factory01 implements ProductFactory{
    @Override
    public ProductA createProductA() {
        return new ShowProductA1();
    }

    @Override
    public ProductB createProductB() {
        return new ShowProductB1();
    }
}
  • Factory02
public class Factory02 implements ProductFactory{
    @Override
    public ProductA createProductA() {
        return new ShowProductA2();
    }

    @Override
    public ProductB createProductB() {
        return new ShowProductB2();
    }
}

改进后的程序为了便于理解、我们不在以做鸡为例、以电子厂为例、比较好描述、做鸡做鸭同理。
电子厂可以做手机、平板、电脑、但是会有不同的品牌、就是产品族的问题。

  • Phone
public abstract class Phone {
    // 呼叫
    public abstract void call();
    // 充话费
    public abstract void addMoney();

}
  • TabletPC
public abstract class TabletPC {
    // 看电视
    public abstract void watchTV();
    // 游戏
    public abstract void playGame();

}

-Computer

public abstract class Computer {
    // 敲代码
    public abstract void code();
    // 玩虚拟机
    public abstract void playLinux();
}
  • ApplePhone
public class ApplePhone extends Phone{
    @Override
    public void call() {
        System.out.println("打电话");
    }

    @Override
    public void addMoney() {
        System.out.println("充话费");
    }
}
  • HuaWeiPhone
public class HuaWeiPhone extends Phone{
    @Override
    public void call() {
        System.out.println("打电话");
    }

    @Override
    public void addMoney() {
        System.out.println("充话费");
    }
}

-Ipad

public class Ipad extends TabletPC{
    @Override
    public void watchTV() {
        System.out.println("看剧");
    }

    @Override
    public void playGame() {
        System.out.println("玩游戏");
    }
}
  • HuaWeiPad
public class HuaWeiPad extends TabletPC{
    @Override
    public void watchTV() {
        System.out.println("看电视");
    }

    @Override
    public void playGame() {
        System.out.println("玩游戏");
    }
}
  • MacBookPro
public class MacBookPro extends Computer{
    @Override
    public void code() {
        System.out.println("敲代码");
    }

    @Override
    public void playLinux() {
        System.out.println("虚拟机");
    }
}
  • MateBookPro
public class MateBookPro extends Computer{
    @Override
    public void code() {
        System.out.println("敲代码");
    }

    @Override
    public void playLinux() {
        System.out.println("虚拟机");
    }
}
  • ElectronicsFactory
public interface ElectronicsFactory {

    public Phone createPhone();

    public TabletPC createTabletPC();

    public Computer createComputer();

}
  • AppleFactory
public class AppleFactory implements ElectronicsFactory{
    @Override
    public Phone createPhone() {
        return new ApplePhone();
    }

    @Override
    public TabletPC createTabletPC() {
        return new Ipad();
    }

    @Override
    public Computer createComputer() {
        return new MacBookPro();
    }
}
  • HuaWeiFactory
public class HuaWeiFactory implements ElectronicsFactory{
    @Override
    public Phone createPhone() {
        return new HuaWeiPhone();
    }

    @Override
    public TabletPC createTabletPC() {
        return new HuaWeiPad();
    }

    @Override
    public Computer createComputer() {
        return new MateBookPro();
    }
}
优点

抽象工厂模式除了具有工厂方法模式的优点外,其他主要优点如下。

  • 可以在类的内部对产品族中相关联的多等级产品共同管理,而不必专门引入多个新的类来进行管理。(即同一个工厂类中可以生产不同的产品,它们属于不同等级,但不必要使用多个类来管理。)
  • 当需要产品族时,抽象工厂可以保证客户端始终只使用同一个产品的产品族。
  • 抽象工厂增强了程序的可扩展性,当增加一个新的产品族时,不需要修改原代码,满足开闭原则。(当需要增加新的产品族时,只需要继承抽象类,自定义实现即可,不需要修改源代码。)
缺点
  • 当产品族中需要增加一个新的产品时,所有的工厂类都需要进行修改。增加了系统的抽象性和理解难度。(虽然增加产品族很容易,但是增加新产品却不容易了,因为产品是由工厂生产,所以必须修改所有的工厂类。)
源码引用(待完成)
引用

设计模式详解_二木成林
尚硅谷设计模式详解

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值