【问题标题】:use signton and factory design pattern使用signton和工厂设计模式
【发布时间】:2020-12-07 17:46:21
【问题描述】:
file AuthLogin.js            

            import axios from "axios";
            const LISTS = {
              USER: "Users",
              STAFF: "DoStaff",
              DOCTOR: "ctor",
              CLINIC: "Clinic",
              EPHARMACY_ADMIN: "EpharmacyAdmin",
            };
            
            // const baseURL = "https://user.api.edoctor.io";
            const baseURL = process.env.USER_API;
            
            const AuthLogin = () => {
              const AuthAPI = (() => {
                var instance;
            
                const http = axios.create({
                  baseURL: baseURL,
                  headers: {
                    Accept: "application/json",
                    "Content-Type": "application/json",
                  },
                });
            
                const createInstance = () => {
                  return {
                    signOut: (url) => signOut(url),
                    signIn: (url, payload) => signIn(url, payload),
                    signInFB: (url, payload) => signInFB(url, payload),
                    signInSmsVerify: (url, payload) => signInSmsVerify(url, payload),
                    signInSmsRequest: (url, payload) => signInSmsRequest(url, payload),
                    signInGoogle: (url, platform, idToken) =>
                      signInGoogle(url, platform, idToken),
                  };
                };
            
                const signInSmsRequest = async (url, payload) => {
                  await http.post(url, payload);
                };
            
                const signInSmsVerify = async (url, payload) => {
                  const response = await http.post(url, payload);
                  return response?.data;
                };
            
                const signIn = async (url, payload) => {
                  const response = await http.post(url, payload);
                  return response?.data;
                };
            
                const signInFB = async (url, accessToken) => {
                  const response = await http.post(url, { accessToken });
                  return response?.data;
                };
            
                const signInGoogle = async (url, platform, idToken) => {
                  const response = await http.post(url, { platform, idToken });
                  return response?.data;
                };
            
                const signOut = async (url) => {
                  return "signOut";
                  // return await http.post("auth/sign_out", {});
                };
            
                return {
                  getInstance: () => {
                    if (!instance) instance = createInstance();
                    return instance;
                  },
                };
              })();
            
              const authFactory = (() => {
                const createAuth = function (type) {
                  return getLists(type);
                };
                return { createAuth };
              })();
            
              const getLists = (type) => {
                var lists = {
                  Doctor: () => {
                    return {
                      signInSmsRequest: (url, payload) =>
                        authAPI.signInSmsRequest(url, payload),
                      signInSmsVerify: (url, payload) =>
                        authAPI.signInSmsVerify(url, payload),
                    };
                  },
                  EpharmacyAdmin: () => {
                    return {
                      signOut: (url) => authAPI.signOut(url),
                      signIn: (url, payload) => authAPI.signIn(url, payload),
                    };
                  },
                };
                return lists[type]();
              };
            
              var authAPI = AuthAPI.getInstance();
            
              return {
                LISTS,
                useAPI: () => authAPI,
                useAuth: (key) => authFactory.createAuth(key),
              };
            };
            export default AuthLogin;
       
file App.js
          const { useAPI, LISTS, useAuth } = AuthLogin();
          useEffect(() => {
            (async () => {
            await useAuth(LISTS.EPHARMACY_ADMIN).signOut();
            })();
          }, []);
    

单例在需要从单个中心位置协调系统范围的操作的情况下很有用。一个例子是数据库连接池。池管理整个应用程序的所有数据库连接的创建、销毁和生命周期,确保没有“丢失”连接。

抽象工厂创建由共同主题相关的对象。在面向对象编程中,工厂是创建其他对象的对象。抽象工厂抽象出了一个由新创建的对象共享的主题。

我正在尝试理解一个非常常用的设计模式 Factory 和 signton,我已经将最好的设计模式放在一起,但我的代码重叠很多,我还没有解决方法,也不知道。更优化?希望你能帮忙?

【问题讨论】:

    标签: javascript reactjs oop factory


    【解决方案1】:

    OOP 原则可以在 React 中使用,但由于 React 处理 state 和重新渲染的方式,它并不总是完全相同。

    当您在 React 中遇到“单例”类型的情况时,通常您想要做的是使用 Context.Provider 使相同的实例可用于您的整个应用程序。例如,如果用户已登录,并且我们希望提供他们的用户详细信息和身份验证令牌,以便我们可以在树中更深的其他组件中访问它们。

    您的AuthLogin 似乎没有任何实例变量,因为baseURL 是一个常量。它也可以是static,或者你可以有独立的功能。每个实例本质上是相同的。这与诸如“会话”之类的东西形成鲜明对比,您可以在其中创建无限多个独特的会话,但我们希望始终访问同一个不同的会话。这就是单例和Context 的意义所在。

    就重复登录而言,您可以拥有一个幕后实用功能,而您的其他功能只需将参数映射到它即可。你的signIn 已经这样做了:

    const signIn = async (url, payload) => {
      const response = await http.post(url, payload);
      return response?.data;
    };
    

    signInSmsVerify 是一个相同的函数,不需要存在。如果需要,您可以将其保留为变量,但只需将其分配给现有函数。

    const signInSmsVerify = signIn
    

    signInGooglesignInFB 将它们唯一的函数参数映射到 payload 对象。您可以创建接受这些参数的函数,然后使用它们调用signIn 函数。

    const signInGoogle = (url, platform, idToken) => signIn(url, { platform, idToken })
    

    (另一种结构是具有创建唯一有效负载的函数,例如 googlePayload = (platform, idToken) => ({ platform, idToken }) 而不是函数 signInGoogle,您可以通过调用 signIn(url, googlePayload(platform, idToken)) 使用 Google 登录。我实际上更喜欢这个,但我不想偏离你要去的地方太远)

    const createInstance = () => {
      return {
        signOut: (url) => signOut(url),
        signIn: (url, payload) => signIn(url, payload),
        signInFB: (url, payload) => signInFB(url, payload),
        signInSmsVerify: (url, payload) => signInSmsVerify(url, payload),
        signInSmsRequest: (url, payload) => signInSmsRequest(url, payload),
        signInGoogle: (url, platform, idToken) =>
          signInGoogle(url, platform, idToken),
      };
    };
    

    这里的参数映射是完全没有必要的,因为它们已经是箭头函数。您可以直接返回const 函数:

    const createInstance = () => {
      return {
        signOut,
        signIn,
        signInFB,
        signInSmsVerify,
        signInSmsRequest,
        signInGoogle
      };
    };
    

    或者您可以完全避免创建这些函数,并使用此返回对象作为将参数映射到核心 signIn 函数的一种方式。

    const createAuthHelper = (http) => {
      const signIn = async (url, payload) => {
        const response = await http.post(url, payload);
        return response?.data;
      };
    
      return ({
        signIn,
        signInSmsVerify: signIn,
        signInSmsRequest: http.post, // not sure why this is needed
        signInFB: (url, accessToken) => signIn(url, { accessToken }),
        signInGoogle: (url, platform, idToken) => signIn(url, { platform, idToken }),
      })
    }
    

    在这里,我将http 对象作为参数传递,以使其灵活且可重用。但是您可以使用它来创建一个全局常量。

    const http = axios.create({
      baseURL: process.env.USER_API,
      headers: {
        Accept: "application/json",
        "Content-Type": "application/json",
      },
    });
    
    const myAuthHelper = createAuthHelper(http);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-28
      相关资源
      最近更新 更多