Заводской режим, начиная со стороннего входа

Шаблоны проектирования

Сегодня при входе в систему на многих платформах ниже будет ряд опций, вы можете выбрать учетные записи WeChat, QQ, Weibo и т. д. для входа в систему. Все эти учетные записи являются сторонними учетными записями для платформы. Вход в учетную запись третьей стороны стал популярным в последние годы, и вход в учетную запись третьей стороны обычно основан наOAuth2.0разработан протокол. если ты не понимаешьOAuth2.0Соглашение, вы можете Baidu самостоятельно, это может быть полезно для вас, чтобы прочитать эту статью.

Теперь, когда компания хочет ввести трафик на платформу, чтобы снизить порог регистрации и позволить большему количеству людей использовать вашу платформу, лидер решил получить доступ к функции входа в сторонний аккаунт на вашей платформе. На этом этапе для входа в систему сначала используются четыре сторонних аккаунта WeChat, Alipay, QQ и GitHub. Эта задача тоже ложится на вашу голову гладко, потому что вы понимаетеOAuth2.0Протокол, как вы знаете, это фиксированная трехэтапная операция, первый шаг — получитьAuthorization Code, вторым шагом является получениеAccess Token, третий шаг вызывает информационный интерфейс, но поля или форматы данных, возвращаемые каждой платформой, могут быть разными, поэтому вы извлекли модуль входа в учетную запись стороннего производителя на основе вашего опыта разработки.IdentityProviderАбстрактный класс, который в основном имеет интерфейсы, необходимые для трех шагов, упомянутых выше,IdentityProviderКод для класса выглядит следующим образом:

public abstract class IdentityProvider {

    // 获取Authorization Code
    abstract void authorizationCode();

    // 获取 Access Token
    abstract void accessToken();

    // 获取用户信息
    abstract void getUserInfo();
}

Каждая сторонняя платформа учетной записи наследуетIdentityProvider, в соответствии с правилами каждой сторонней платформы учетных записей для реализации этих трех интерфейсов, мы взяли Alipay в качестве примера, мы определяемAliPayIdentityProviderкласс, который наследуетIdentityProviderДобрый,AliPayIdentityProviderКод класса выглядит следующим образом:


/**
 * 支付宝 第三方登陆具体实现
 */
public class AliPayIdentityProvider extends IdentityProvider{

    private static final String APPID = "你申请的运用id";
    private static final String APPKEY = "你的私钥";

    public AliPayIdentityProvider() {
        System.out.println("我是支付宝第三方登陆具体实现");
    }

    @Override
    abstract void getUserInfo(){
        // 获取用户信息
    }

    @Override
    public void authorizationCode() {
        //获取authorization Code
    }

    @Override
    public void accessToken() {
        //获取access Token
    }
}

Четыре сторонних платформ входа в систему учетных записей были реализованы вышеупомянутыми. Кроме того, вы также создалиIdentityFactoryкласс, который является единственной записью для создания экземпляра, предоставляющего статическийcreateметод,createФункция метода заключается в возврате соответствующего экземпляра платформы сторонней учетной записи в соответствии с входящими параметрами.IdentityFactoryКод класса выглядит следующим образом:

public class IdentityFactory {
    /**
     * 第三方登陆实例获取
     * @param type 标识符,1:支付宝登陆 2:微信登陆 3:QQ登录 4:github登陆 
     */
    public static IdentityProvider create(int type){
        IdentityProvider identityProvider = null;
        switch (type){
            case 1:
                identityProvider = new AliPayIdentityProvider();
                break;
            case 2:
                identityProvider = new WeChatIdentityProvider();
                break;
            case 3:
                identityProvider = new QQIdentityProvider();
                break;
            case 4:
                identityProvider = new GitHubIdentityProvider();
                break;
        }
        return identityProvider;
    }
}

Когда клиент звонит, ему нужно только позвонитьcreate()Метод может получить соответствующий экземпляр, например, для использованияGitHubВход в учетную запись, нам просто нужно позвонитьIdentityProvider identityProvider = IdentityFactory.create(4);, получатьGitHubизIdentityProvider, после получения объекта вы можетеGitHubСпецифическая операция входа в учетную запись. Отправьте, разверните, протестируйте, подключитесь к сети и выполните задачу идеально.

При реализации функции входа на платформу сторонней учетной записи вы используете шаблон проектирования, называемыйПростой заводской шаблон, в этот момент вы, должно быть, кричите в своем сердце, что, черт возьми, это использует шаблоны проектирования? Да, верно, это шаблон проектирования. Раз уж вам любопытно, давайте взглянем на простой фабричный шаблон.

Определение простого фабричного шаблона

Простой фабричный паттерн: также известный как паттерн статического фабричного метода, это тип созидательного паттерна. В простом фабричном шаблоне есть фабричный класс, который отвечает за создание экземпляров других классов.Эти созданные экземплярные классы имеют общий родительский класс.В нашей сторонней учетной записи логинAliPayIdentityProvider,WeChatIdentityProviderОба класса являются экземплярами, все они имеют общий родительский класс.IdentityProvider, в простом фабричном шаблоне фабричный класс может возвращать разные экземпляры в соответствии с входящими параметрами, в нашемIdentityFactoryкласс, мы предоставляем статическийcreate(int type), который может возвращать разные экземпляры в зависимости от переданного типа. Итак, у нас есть пример стандартного паттерна Simple Factory.

Приведенный выше абзац не легко понять? Неважно, давайте абстрагируемся, простой фабричный шаблон в основном состоит из следующих трех членов:

  • Абстрактный продукт: Роль абстрактного продукта является родительским классом всех созданных объектов и отвечает за описание общего интерфейса, общего для всех экземпляров, напримерIdentityProvider
  • Конкретный продукт: конкретная роль продукта является целью создания, и все созданные объекты действуют как экземпляры определенного класса этой роли, напримерAliPayIdentityProvider
  • Фабричный класс: отвечает за реализацию внутренней логики для создания всех экземпляров, например.IdentityFactory

Давайте еще раз взглянем на UML-диаграмму простого фабричного шаблона:

Они должны понимать простой заводской режим, хотя в названии есть слово простой, но по здравому смыслу, даже если он простой, должны быть некоторые преимущества. Поскольку вам все еще любопытно, давайте перейдем к преимуществам простого фабричного шаблона.

Преимущества простого заводского шаблона

  • Фабричный класс содержит необходимую логику суждения, которая может решить, когда создавать экземпляр того или иного класса продукта, а клиент может быть освобожден от ответственности за непосредственное создание объекта продукта, но только «потребляет» продукт; простой фабричный шаблон реализует ответственность за продукт за счет такого подхода.Разделение, которое предоставляет специализированные фабричные классы для создания объектов.
  • Клиенту не нужно знать имя класса созданного конкретного класса продукта, а нужно знать только параметры, соответствующие конкретному классу продукта.Для некоторых сложных имен классов простой заводской режим может уменьшить объем памяти пользователя.
  • Внедряя файлы конфигурации, новые определенные категории продуктов могут быть заменены и добавлены без изменения какого-либо клиентского кода, что в определенной степени повышает гибкость системы.

После того, как была запущена функция входа в сторонний аккаунт, количество пользователей на платформе вашей компании быстро увеличилось, и босс был очень доволен, поэтому он устроил так, чтобы вы снова жили.На этот раз босс попросил вас добавить свою учетную запись Weibo. Войдите в систему, чтобы вы могли использовать свою учетную запись Weibo для входа на свою платформу, с предыдущим опытом это слишком просто для вас. вы добавилиWeiBoIdentityProviderкласс, используемый для реализации входа в учетную запись Weibo,WeiBoIdentityProviderКлассы следующие:


/**
 * 微博账号登陆
 */
public class WeiBoIdentityProvider extends IdentityProvider{

    private static final String APPID = "你申请的运用id";
    private static final String APPKEY = "你的私钥";

    public WeiBoIdentityProvider() {
        System.out.println("我是微博第三方登陆具体实现");
    }

    @Override
    abstract void getUserInfo(){
        // 获取用户信息
    }

    @Override
    public void authorizationCode() {
        //
    }

    @Override
    public void accessToken() {

    }
}

существуетIdentityFactoryдобавлен классcase 5Ветвь, используемая для возврата к экземпляру входа в учетную запись Weibo после изменения.IdentityFactoryКлассы следующие:

public class IdentityFactory {
    /**
     * 第三方登陆验证
     * @param type 标识符,1:支付宝登陆 2:微信登陆 3:QQ登录 4:github登陆 5:微博账号
     */
    public static IdentityProvider crete(int type){
        IdentityProvider identityProvider = null;
        switch (type){
            case 1:
                identityProvider = new AliPayIdentityProvider();
                break;
            case 2:
                identityProvider = new WeChatIdentityProvider();
                break;
            case 3:
                identityProvider = new QQIdentityProvider();
                break;
            case 4:
                identityProvider = new GitHubIdentityProvider();
            case 5:
                identityProvider = new WeiBoIdentityProvider();
                break;
        }
        return identityProvider;
    }
}

Разверните и протестируйте вход в учетную запись Weibo, нет проблем, упакуйте и подключитесь к сети, выключите и уйдите с работы. После запуска большое количество пользователей сообщили, что не удалось войти в учетную запись GitHub. Молодой человек, выходите, чтобы забрать горшок, так что вам придется бежать обратно в компанию, чтобы работать сверхурочно, чтобы исправить ошибки, трудолюбивый программист. Ты искала, искала и наконец нашла,case 4изbreakЗаявление было удалено вами, поэтому, когда вы входите в свою учетную запись GitHub,IdentityFactoryЭкземпляр, возвращаемый фабрикой, всегдаWeiBoIdentityProvider, Ведущий к логину учетной записи GitHub, потерпит неудачу. Небольшое ошибка непреднамеренно, вызвала несчастный случай онлайн. Производство имеет несчастный случай, вы знаете последствия. Хотя эта авария была, но ваши слабости, вызванные человеческой деятельностью, - это простой заводской шаблон, каждый раз, когда вы добавляете стороннюю учетную платформу входа в систему, нам нужно изменить заводский класс, который неизбежно будет случай такого случайного удаления. Простой заводской шаблон прост, но есть много недостатков, то мы взглянем на простой заводской шаблон, каковы недостатки этого.

Недостатки простого фабричного шаблона

  • Нарушая принцип «открыто-закрыто», после добавления нового продукта логика фабричного класса должна быть изменена, что легко вызвать ошибки, как мы сделали выше, случайно вызывая онлайн-аварии.
  • Класс фабрики концентрирует логику создания всех экземпляров (продуктов).Если фабрика не работает должным образом, это повлияет на всю систему.
  • Простой фабричный шаблон использует статический фабричный метод, поэтому роль фабрики не может формировать иерархическую структуру, основанную на наследовании.

После этого несчастного случая вы стремитесь проявить себя и восстановить признание своих лидеров.Вы полны решимости провести рефакторинг модуля входа в сторонний аккаунт. Как говорится в старой поговорке: вставай, где упадешь. Вот вы думаете-думаете, и вот наконец у вас есть идея, которую нужно исправитьIdentityFactoryКогда класс подвергается рефакторингу, фабричный класс также должен извлекать абстрактный класс, такой как провайдер, и тогда каждый провайдер имеет свою собственную фабрику, чтобы избежать изменений в исходных системных модулях при их добавлении. Итак, вы абстрагируетеIdentityProviderFactoryКласс, используемый для определения интерфейса, требуемого фабрикой.IdentityProviderFactoryКлассы следующие:

/**
 * 第三方登陆抽象工厂
 */
public abstract class IdentityProviderFactory<T> {
    // 创建具体的IdentityProvider
    public abstract IdentityProvider create();
}

Каждая сторонняя платформа учетных записей должна иметь свою собственную производственную фабрику, которая должна наследоватьIdentityProviderFactoryкласс, затем переопределитьcreate()метод, вcreate()создать свой собственный экземплярidentityProviderКласс реализации, в качестве примера возьмем фабрику Alipay, нам нужно создатьAliPayIdentityProviderFactoryДобрый,AliPayIdentityProviderFactoryКод класса выглядит следующим образом:

/**
 * 支付宝第三方登陆工厂类
 */
public class AliPayIdentityProviderFactory extends IdentityProviderFactory<AliPayIdentityProvider> {
    @Override
    public IdentityProvider create() {
        //支付宝登录实现实例
        return new AliPayIdentityProvider();
    }
}

существуетcreate()возврат методаAliPayIdentityProviderЭкземпляры, каждая фабрика может вернуть соответствующий экземпляр.При вызове клиента также должны быть внесены соответствующие изменения.Вместо передачи параметров для получения экземпляра экземпляр получается путем вызова соответствующей фабрики. Например, мы используем учетную запись Alipay для входа в систему.

// 调用支付宝工厂
IdentityProviderFactory providerFactory  = new AliPayIdentityProviderFactory();
// 获取IdentityProvider
IdentityProvider provider = providerFactory.create();
// 一些列第三方认证操作

После рефакторинга последней проблемы у нас точно не будет, ведь теперь у каждого стороннего провайдера аккаунтов своя фабрика, а сборка и работа каждого продукта независимы. Поздравляю, парень, ты недалек от повышения и прибавки.

В процессе вашего рефакторинга вы также обновили шаблон простой фабрики. Теперь он не называется шаблоном простой фабрики, потому что он уже не простой. Текущий шаблон называется шаблоном простой фабрики.Шаблон фабричного метода. Теперь, когда мы все использовали шаблон фабричного метода, давайте взглянем на шаблон фабричного метода.

Определение шаблона фабричного метода

Шаблон фабричного метода, также известный как фабричный шаблон, шаблон виртуального конструктора или полиморфный фабричный шаблон, также является типом шаблона создания класса. Разница между шаблоном фабричный метод и простым фабричным шаблоном заключается в том, что в шаблоне фабричный метод создание экземпляров не сосредоточено в фабрике, а извлекается родительский класс фабрики, а родительский класс фабрики отвечает за определение общедоступного интерфейс для создания объектов продукта, в то время как подкласс factory отвечает за создание конкретных объектов продукта. Цель этого состоит в том, чтобы отложить создание экземпляра класса продукта до подкласса factory. То есть подкласс factory определяет, какой конкретный класс продукта должен быть создан. . как у насIdentityProviderFactoryкласс иAliPayIdentityProviderFactoryДобрый.

Подобно простому фабричному шаблону, мы также абстрагируем шаблон фабричного метода, который состоит из следующих четырех членов:

  • Абстрактный продукт: определите методы атрибутов, которые есть у продукта, такие какIdentityProvider
  • Конкретный продукт: конкретная реализация продукта, например.AliPayIdentityProvider
  • Абстрактная фабрика: определите абстрактный метод фабрики, напримерIdentityProviderFactory
  • Бетонный завод: конкретное производственное предприятие, напримерAliPayIdentityProviderFactory

Старая практика, давайте взглянем на UML-диаграмму шаблона фабричного метода, чтобы углубить впечатление:

Преимущества шаблона фабричный метод Когда мы проводили рефакторинг модуля входа в систему сторонней учетной записи, мы уже убедились, что преимущества шаблона фабричного метода не ограничиваются этим.Давайте рассмотрим преимущества шаблона фабричного метода.

Преимущества шаблона фабричного метода

  • Шаблон фабричного метода очень расширяем.При добавлении новых продуктов в систему нет необходимости изменять интерфейсы, предоставляемые абстрактной фабрикой и абстрактными продуктами, а нужно только добавлять конкретную фабрику и конкретный продукт, чтобы принять изменения, точно так же, как если мы сейчас подключимся Чтобы войти в учетную запись DingTalk, нам нужно только создатьDingDingIdentityProviderFactoryа такжеDingDingIdentityProviderДостаточно
  • Хорошая инкапсуляция, четкая структура кода. Когда вызывающему объекту нужен конкретный объект продукта, ему нужно знать только имя класса продукта и не нужно знать конкретный процесс создания, что уменьшает связь между модулями.
  • Экранирование класса продукта, как меняется реализация класса продукта, вызывающей стороне не нужна связь, она относится только к интерфейсу продукта, пока интерфейс остается неизменным, модули верхнего уровня в системе не нужно изменить. Поэтому шаблон фабричный метод часто используется для разделения.Модулю высокого уровня нужно знать только абстрактный класс продукта, а класс реализации не нуждается в отношениях.Это соответствует закону Деметры и принципу зависимости инверсия.

Хотя паттерн фабричный метод имеет много преимуществ, он также имеет много недостатков, потому что невозможно иметь идеальный шаблон проектирования, поэтому давайте рассмотрим недостатки паттерна фабричный метод.

Недостатки шаблона фабричного метода

  • Увеличивая сложность системы, мы разделяем фабричный класс, что незаметно усложняет нашу систему.
  • Увеличивает объем разработки, при использовании простого фабричного шаблона мы хотим добавить толькоcaseветка, теперь вам нужно создать класс
  • Учитывая масштабируемость системы, необходимо ввести уровень абстракции, который определяется в клиентском коде, что увеличивает абстракцию и сложность понимания системы, а также может потребовать использования DOM, отражения и других технологий при реализации. сложность внедрения системы

Суммировать

В этой статье в основном кратко представлены два шаблона проектирования: простой фабричный шаблон и фабричный метод.Войдите в этот случай через стороннюю учетную запись, начиная с простого фабричного шаблона и шаг за шагом к шаблону фабричного метода. Если вы хотите глубже понять фабричный шаблон, вам нужно обратиться к большому количеству случаев.springВ фреймворках с открытым исходным кодом используется большое количество шаблонов проектирования, и шаблон фабрики, естественно, незаменим.Независимо от того, какой шаблон проектирования вы изучаете, мы можем обратиться к этим фреймворкам с открытым исходным кодом, которые могут углубить ваше понимание шаблонов проектирования.

исходный код

Что касается недостатков статьи, я надеюсь, что вы можете дать больше указаний, учиться вместе и вместе добиваться прогресса.

наконец

Сделайте небольшую рекламу, добро пожаловать, чтобы отсканировать код и подпишитесь на общедоступную учетную запись WeChat: «Технический блог брата Пинтоу», давайте вместе добьемся прогресса.

平头哥的技术博文