其他分享
首页 > 其他分享> > [设计模式]工厂模式

[设计模式]工厂模式

作者:互联网

[设计模式]工厂模式

目录

手机用户请横屏获取最佳阅读体验,REFERENCES中是本文参考的链接,如需要链接和更多资源,可以关注其他博客发布地址。

平台 地址
CSDN https://blog.csdn.net/sinat_28690417
简书 https://www.jianshu.com/u/3032cc862300
个人博客 https://yiyuery.github.io/NoteBooks/

工厂模式是个统一的泛称,具体可以分为:

其中,简单工厂是种编程的习惯,并不是种设计模式。静态工厂则是简单工厂的一种变体,即使用静态方法定义一个简单工厂,我们就称之为静态工厂.

工厂模式处理的是对象的创建的统一封装问题。

静态工厂

场景描述

背景:

一个工厂有个手机生产线,可以支持生产和组装不同品牌的手机,不同的代理商需要向工厂订购不同数量、不同类型的手机。

初始问题:

不同手机的代理商每次需要进不同品牌的手机。每次去找工厂的时候,都会 new 一个新的手机出来。那么M种品牌代理商的话,如果在工厂都下订单,工厂需要定义 M 个手机对象。如果某个品牌该代理商暂时不使用了,但是其他代理商还要使用,工厂就需要修改给代理商提供手机的类。

对于这个问题,我们用静态工厂来看下如何解决:

在这里插入图片描述

//抽象手机对象
@Data
public abstract class AbstractPhone {

    /**
     * 手机品牌名称
     */
    private String name;

    /**
     * 展示手机信息
     *
     * @return
     */
    public void showInfo() {
        System.out.println("Hi,you has ordered a/an " + getName());
    }
}
//代理商,淘宝或是天猫等
public class SimpleIPhoneAgent {

    /**
     * 订购一个IPHONE
     * @return
     */
    public AbstractPhone orderPhone(){
        return SimplePhoneFactory.produce(PhoneType.PHONE_TYPE_IPHONE);
    }
}

//静态工厂
public class SimplePhoneFactory {

    /**
     * 生产
     *
     * @return
     */
    public static AbstractPhone produce(PhoneType type) {
        AbstractPhone phone = null;
        switch (type) {
            case PHONE_TYPE_XIAOMI:
                phone = new Xiaomi();
                break;
            case PHONE_TYPE_IPHONE:
                phone = new IPhone();
                break;
            default:
                break;
        }
        return phone;
    }
}
//iPhone
public class IPhone extends AbstractPhone {

    public IPhone() {
        setName(PhoneType.PHONE_TYPE_IPHONE.getType());
    }
}
//枚举类
@AllArgsConstructor
@Getter
public enum PhoneType {

    /**
     * 手机品牌类型
     */
    PHONE_TYPE_IPHONE("iPhone"),
    PHONE_TYPE_XIAOMI("Xiaomi");

    private String type;
}

测试

 /**
  * 简单工厂
  */
@Test
public void testX1(){
    AbstractPhone iphone = new SimpleIPhoneAgent().orderPhone();
    iphone.showInfo();
    //Hi,you has ordered a/an iPhone
}

简单工厂(静态工厂),虽然不是真正的设计模式,但不失为一个简单的方法,可以将客户程序从具体类解耦。

工厂方法模式

定义了一个创建对象的接口,但是由子类决定要实例化的类是哪一个。工厂方法模式是让类把实例化推迟到子类。

在之前的场景下,我们有很多的代理商都从同一个工厂订购手机。但是如果生产手机的工厂由于设备老旧或是资金不足无法生产新型手机怎么办?
以生产新的iphone7和小米6手机为背景,我们来看下工厂方式模式怎么实现的?

在这里插入图片描述

//抽象的手机代理商类中声明了一个工厂方法,供子类实现具体的生产方式。
abstract class AbstractAgent {

    /**
     * 订购
     * @return
     */
    public AbstractPhone orderPhone(PhoneType type){
        //调用子类实现的工厂方法
        return producePhone(type);
    }

    /**
     * 声明工厂方法
     * @param type
     * @return
     */
    abstract AbstractPhone producePhone(PhoneType type);
}

//新的工厂
public class NewPhoneFactory {

    /**
     * 生产
     *
     * @return
     */
    public static AbstractPhone produce(PhoneType type) {
        AbstractPhone phone = null;
        switch (type) {
            case PHONE_TYPE_XIAOMI_6:
                phone = new Xiaomi6();
                break;
            case PHONE_TYPE_IPHONE_7:
                phone = new IPhone7();
                break;
            default:
                break;
        }
        return phone;
    }
}

//京东代理商选择新的工厂来生产手机
public class JDAgent extends AbstractAgent {
    /**
     * 声明工厂方法
     *
     * @param type
     * @return
     */
    @Override
    AbstractPhone producePhone(PhoneType type) {
        return NewPhoneFactory.produce(type);
    }
}

测试

/**
 * 工厂方法模式
 */
@Test
public void testX2(){
    AbstractPhone iphone7 = new JDAgent().orderPhone(PhoneType.PHONE_TYPE_IPHONE_7);
    iphone7.showInfo();
    //Hi,you has ordered a/an iPhone 7
}

抽象工厂模式

抽象工厂模式提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类

顾名思义,抽象工厂就是把工厂通过接口或是超类抽象定义出来,以满足不同手机的生产可以依赖不同工厂,但是对于调用方无感,只需要传入对应的工厂实例即可。

在这里插入图片描述

之前提供一系列的静态工厂实例类来直接实现代理商所需手机的生产工作(如前文的SimplePhoneFactory、NewPhoneFactory)。考虑到一旦工厂不再生产对应的手机了,我们就必须得修改多处代码,一个代理商的在生产前的工厂调用,一是工厂实例内的switch选择。

我们改造下上面的工厂方法模式,将工厂对象抽象出来,

//工厂的抽象接口定义
public interface PhoneFactory {

    /**
     * 生产
     * @return
     */
    AbstractPhone produce(PhoneType type);
}

//富士康工厂定义
public class FushikangFactory implements PhoneFactory {
    /**
     * 生产
     *
     * @return
     */
    @Override
    public AbstractPhone produce(PhoneType type) {
        AbstractPhone phone = null;
        switch (type) {
            case PHONE_TYPE_IPHONE_8:
                phone = new IPhone8();
                break;
            case PHONE_TYPE_IPHONE_X:
                throw new IllegalArgumentException("NOT SUPPOT IPHONE X");
            default:
                break;
        }
        return phone;
    }
}

//代理商基类补充工厂属性定义(Lombok自动生成了全参构造器和Getter\Setter方法)
@Data
@AllArgsConstructor
@NoArgsConstructor
public abstract class AbstractAgent {

    /**
     * 服务于抽象工厂模式
     */
    private PhoneFactory factory;

    /**
     * 订购
     * @return
     */
    public AbstractPhone orderPhone(PhoneType type){
        //调用子类实现的工厂方法
        return producePhone(type);
    }

    /**
     * 声明工厂方法
     * @param type
     * @return
     */
    protected abstract AbstractPhone producePhone(PhoneType type);
}
//新的代理商苏宁易购
public class SuningAgent extends AbstractAgent {

    //提供入口传入使用的工厂实例
    public SuningAgent(PhoneFactory factory) {
        super(factory);
    }

    /**
     * 声明工厂方法
     *
     * @param type
     * @return
     */
    @Override
    protected AbstractPhone producePhone(PhoneType type) {
        return getFactory().produce(type);
    }
}

测试

 /**
  * 抽象工厂模式
  */
@Test
public void testX3(){
    SuningAgent suningAgent = new SuningAgent(new FushikangFactory());
    AbstractPhone phone = suningAgent.orderPhone(PhoneType.PHONE_TYPE_IPHONE_8);
    phone.showInfo();
    phone = suningAgent.orderPhone(PhoneType.PHONE_TYPE_IPHONE_X);
    phone.showInfo();
    
    //Hi,you has ordered a/an iPhone 8

    //java.lang.IllegalArgumentException: NOT SUPPOT IPHONE X
}

抽象工厂的接口定义中,还可以定义不同的产品系列,这是它相对于工厂方法模式,更容易扩展的地方。

总结

工厂方法模式特点

抽象工厂模式特点

相同点

设计基础

OO原则

REFERENCES

《Head First》读书笔记

更多

扫码关注架构探险之道,回复文章标题,获取本文相关源码和资源链接

在这里插入图片描述

知识星球(扫码加入获取历史源码和文章资源链接)

在这里插入图片描述

标签:return,模式,工厂,PhoneType,设计模式,type,public,AbstractPhone
来源: https://blog.51cto.com/u_15263565/2886097