Python设计模式之代理模式

代理模式目录

代理模式

概念

  • 代理就是一个中间系统
  • 代理模式关键在于对外屏蔽真实对象
  • 通过代购可以类比一下

演员与经纪人的例子来理解一下:

class Actor(object):
    def __init__(self):
        self.is_busy = False

    def occupied(self):
        self.is_busy = True
        print(type(self).__name__, '正在拍电影')

    def available(self):
        self.is_busy = False
        print(type(self).__name__, '正在休息')

    def get_status(self):
        return self.is_busy

class Agent(object):
    def __init__(self):
        self.principal = None

    def work(self):
        # 给他一个演员
        self.actor = Actor()
        # 如果在忙就休息,如果在休息就忙起来
        if self.actor.get_status():
            self.actor.occupied()
        else:
            self.actor.available()

代理维护一个引用,代理通过这个引用访问实际对象。代理也负责创建和删除真实业务。


实现:

再来一个例子实现一个规模较大的代理:
付款系统

  • 用户行为由类User表示
  • 为了购买衣服,User类提供pay方法
  • 魔法方法__init__调用代理并将其实例化
  • pay方法在内部调用代理的方法进行付款
  • 付款成功,返回__del__方法
class User(object):
    def __init__(self):
        self.debit_card = DebitCard()
        self.is_purchased = None

    def pay(self, card_id):
        self.is_purchased = self.debit_card.do_pay(card_id)

    def __del__(self):
        if self.is_purchased:
            print('购买成功')
        else:
            print('购买失败')


# 主题是付款,是一个抽象基类,
from abc import ABCMeta, abstractmethod
class Payment(metaclass=ABCMeta):
    @abstractmethod
    def do_pay(self):
        pass


# 真实主题银行类
class Bank(Payment):
    def __init__(self):
        self.card = None
        self.account = None

    def __get_acount(self):
        self.account = self.card
        return self.account

    def __has_funds(self):
        print('找到卡号:', self.__get_acount())
        return True

    def set_card(self, card):
        self.card = card

    def do_pay(self):
        if self.__has_funds():
            print('扣款成功')
            return True
        else:
            print('扣款失败')
            return False


# 代理
class DebitCard(Payment):
    def __init__(self):
        self.bank = Bank()

    def do_pay(self, card_id):
        self.bank.set_card(card_id)
        return self.bank.do_pay()


user = User()
user.pay('123456')

代理有什么用?

  • 代理可以通过缓存要频繁访问的对象来提高性能
  • 可以比作:代购
    Python设计模式之代理模式

代理和门面区别

代理模式 门面模式
给其他对象提供了代理或者占位符,以控制对原始对象的访问 为大型子系统提供接口
代理对象和目标对象接口一致,并有对目标的引用 实现子系统之间通信和依赖的最小化
充当客户端和被封装对象的中介 提供单一的简单的接口

常见问题

  • 装饰器和代理区别:
    • 装饰器给正在运行时的对象添加行为,代理是控制对象的访问。代理不是动态的,装饰器是动态的。
  • 代理模式缺点:
    • 增加响应时间,比如代理如果结构不好,就会增加时间。所以取决于代理写的好不好
  • 客户端可以独立访问真实主题吗?
    • 可以,但是代理模式可以提供许多优势:虚拟、远程等。
  • 代理能给自己添加功能吗?
    • 可以,而且无需改对象的代码。代理和真是主题可以实现相同的接口
上一篇:[django项目] 如何在网站上实现文档下载功能?


下一篇:uni-app中如何编写一个promise函数并调用