工厂模式与抽象工厂

原理:逻辑和业务全部封装 不需要细节 只要结果

示例:

# 简单工厂
class SimpleFactory:
    # 产品
    @staticmethod
    def product(name):
        return name


if __name__ == "__main__":
    product = SimpleFactory.product("Gitee")

    print(product)
  • 装饰器@staticmethod,普通方法,类对象实例对象都可应用
  • 装饰的方法类比产品,工厂生产产品,只要最后结果

 抽象工厂实例:

from abc import ABCMeta, abstractmethod  # 抽象工厂

class TestMeta(metaclass=ABCMeta):  继承metaclass=ABCMeta
    def __init__(self):
        self.a = 1

    @abstractmethod
    def fun(self):
        pass


class TestOne(TestMeta):
    def __init__(self):
        super().__init__()  # 调用父类的init
        # TestMeta.__init__()
        self.b = 1

    # 重写抽象方法
    def fun(self):
        print("拼接三方登录的url")
  • 抽象工厂类似于生活中的橘子,橘子的种类繁多,但橘子本体的一些口感(方法)是其他种类必须所拥有的,也就是其他类继承抽象工厂类,必须重写已有的方法,否则报错
  • pass是占位符,抽象工厂中的方法要用装饰器@abstractmethod定义,只定义框架,不写具体逻辑

抽象工厂完成第三方登录基本方法:

class LoginProvide(metaclass=ABCMeta):

    # 跳转拼接
    @abstractmethod
    def get_url(self):
        pass

    # 获取token
    @abstractmethod
    async def get_token(self, code):
        pass

    # 获取用户信息
    @abstractmethod
    async def get_info(self, token):
        pass

    # 用户信息存储
    @abstractmethod
    async def set_user(self, user):
        pass

 gitee登录实例

class GiteeProvider(LoginProvide):
    def __repr__(self):
        return "Gitee登录"

    def get_url(self):
        url = SITE_TYPE["Gitee"]["url"]  # 跳到授权地址
        return url

    async def get_token(self, code):
        # 通过授权码请求token
        # 异步发送网络请求,防止阻塞
        client_id = SITE_TYPE["Gitee"]["client_id"]
        client_secret = SITE_TYPE["Gitee"]["client_secret"]
        redirect_uri = SITE_TYPE["Gitee"]["redirect_uri"]

        async with httpx.AsyncClient() as client:
            res = await client.post(
                url=f"https://gitee.com/oauth/token?grant_type=authorization_code&code={code}&client_id={client_id}&redirect_uri={redirect_uri}&client_secret={client_secret}",
                timeout=20
            )

        res = res.json()

        # 获取gitee的access_token refresh_token
        return res["access_token"]

    async def get_info(self, token):
        async with httpx.AsyncClient() as client:
            res = await client.get(SITE_TYPE["Gitee"]["gitee_get_info_uri"] + token, timeout=20)
            res = res.json()

            user = {
                "gitee_id": res["id"],
                "gitee_username": res["name"]
            }

        return user

    async def set_user(self, user):
        gitee_id = user["gitee_id"]
        gitee_username = user["gitee_username"]
        username = (str(gitee_id) + "_" + str(gitee_username))
        try:
            # 曾经使用过gitee账号
            await db.get(UserModel.select().where((UserModel.username == username)
                                                  & (UserModel.site_type == SITE_TYPE["Gitee"]["num"])))

        except Exception as e:
            print(e.args)
            await db.create(UserModel,
                            username=username,
                            site_type=SITE_TYPE["Gitee"]["num"])

        finally:
            mj = MyJwt()
            # 生成带有生命周期的token
            token = mj.encode_date({
                "username": username,
                "site_type": SITE_TYPE["Gitee"]["num"]
            })
            # 生成refresh_token  redis里面存
            refresh_token = await mj.set_refresh_token(f"{gitee_id}_{gitee_username}")

        # 中间缓存页
        url = SITE_TYPE["Gitee"]["gitee_center_uri"] + f"?gitee_refresh_token={refresh_token}&gitee_token={token}&username={username}"

        return url

Gitee简化版:

# gitee登录简化版
class GiteeFactory(BaseHandler):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.gitee = GiteeProvider()

    async def get(self):
        code = self.get_argument("code")
        access_token = await self.gitee.get_token(code)
        user = await self.gitee.get_info(access_token)
        url = await self.gitee.set_user(user)

        return self.redirect(url)

# 路由
urlpatterns = [
    (r"/gitee_back/", GiteeFactory),  # gitee
]

总结:

  • 利用抽象工厂模式,来编写架子,方便区分步骤,简洁明了
  • 继承抽象工厂必须要重写所有方法
  • 养成良好的代码习惯,方便给客户调用,保护内部细节
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值