python设计模式(2)

系列文章目录

提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加


提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档


1 策略模式

问题引入

商场的打折活动会给出不同的促销方案:
1 原价
2 满300减100
3 总价8折
那么结算时, 如何算出正确的金额, 就可以使用策略模式.

模式定义

策略模式(Strategy Pattern) 是指定义一个算法家族,使得家族内的不同算法都遵从算法家族的接口及方法规范,从而可以实现算法间互相替换,且不会影响到使用算法的客户。

为什么要使用策略模式

策略模式鼓励用多种方法解决一个问题。在运行时动态自动地选择算法。且对代码的理解符合人类的习惯。
避免大量的if else 使得程序的维护和扩展不方便。

解决方案

使用策略模式来解决问题。

  1. 列表项首先创建抽象的算法类CashSupur,作为所有促销活动算法的抽象类,同时定义所有支持算法的公共接口,定义方法acceptCash()用于得到结果;
  2. 列表项创建具体的促销算法类CashNormal,CashRebate等,继承于抽象算法类CashSupur,覆写acceptCash()实现具体的促销算法;
  3. 列表项创建上下文类CashContext,维护对算法对象的引用,使用时根据用户输入,传入一个具体的促销算法类来配置。

代码实现

"""
对商场打折商品计算总价
"""
import tkinter
import tkinter.ttk

from abc import ABCMeta, abstractmethod


class CashSuper(metaclass=ABCMeta):
    @abstractmethod
    def accept_cash(self, money):
        raise NotImplementedError("not implemented")


# 正常收费
class CashNormal(CashSuper):
    def accept_cash(self, money):
        return money


# 打折收费
class CashRebate(CashSuper):
    def __init__(self, moneyRebateStr="1"):
        self.__moneyRebate = float(moneyRebateStr)

    def accept_cash(self, money):
        return money * self.__moneyRebate


# 返利收费
class CashReturn(CashSuper):
    def __init__(self, moneyConditionStr="0", moneyReturnStr="0"):
        self.__moneyCondition = float(moneyConditionStr)
        self.__moneyReturn = float(moneyReturnStr)

    def accept_cash(self, money):
        result = money
        if (money >= self.__moneyCondition):
            result = money - money // self.__moneyCondition * self.__moneyReturn
        return result


class CashContext(object):
    def __init__(self, typ):
        if typ == "正常收费":
            self.cs = CashNormal()
        elif typ == "满300返100":
            self.cs = CashReturn("300", "100")
        elif typ == "打8折":
            self.cs = CashRebate("0.8")

    def get_result(self, money):
        return self.cs.accept_cash(money)


class CashWindow(object):
    def __init__(self):
        self.total = 0
        root = tkinter.Tk()
        self.label1 = tkinter.Label(root, text="单价:")
        self.txtPrice = tkinter.Entry(root, width=24, )
        self.label2 = tkinter.Label(root, text="数量:")
        self.txtNum = tkinter.Entry(root, width=24, )
        self.ibxList = tkinter.Text(root, width=45, height=10)
        self.label4 = tkinter.Label(root, text="总计:")

        self.iblResult = tkinter.StringVar()
        self.iblResult.set("%.2f" % self.total)
        self.result = tkinter.Label(root, textvariable=self.iblResult, height=2, font=('TimeNewsRoman', 24))
        self.button = tkinter.Button(root, text="确定", width=10, command=self.btnOk_click)
        self.buttonReset = tkinter.Button(root, text="重置", width=10, command=self.btnReset_click)

        self.label3 = tkinter.Label(root, text="计算方式:")
        self.comboVar = tkinter.StringVar()
        self.combobox = tkinter.ttk.Combobox(root, textvariable=self.comboVar, width=22, )
        self.combobox['value'] = ("正常收费", "打8折", "满300返100")
        self.combobox.current(0)
        self.layout()
        root.mainloop()

    def refresh(self):
        self.txtPrice.delete('0', 'end')
        self.txtNum.delete('0', 'end')

    def layout(self):
        self.label1.grid(row=0, column=0, padx=(10, 0), pady=10)
        self.txtPrice.grid(row=0, column=1, pady=10, padx=(0, 5), )
        self.label2.grid(row=1, column=0, padx=(10, 0))
        self.txtNum.grid(row=1, column=1, padx=(0, 5), )
        self.label3.grid(row=2, column=0, padx=(10, 0))
        self.combobox.grid(row=2, column=1, padx=(0, 5), pady=10)

        self.ibxList.grid(row=4, column=0, columnspan=4, padx=(5, 5), pady=10)
        self.label4.grid(row=5, column=0, padx=(10, 0))
        self.result.grid(row=5, column=1, columnspan=3, rowspan=2)
        self.button.grid(row=0, column=2, columnspan=2, pady=10, padx=(0, 10))
        self.buttonReset.grid(row=1, column=2, columnspan=2, padx=(0, 10))

    def btnReset_click(self):
        self.total = 0
        self.ibxList.delete('1.0', 'end')
        self.iblResult.set("%.2f" % self.total)
        self.refresh()

    # 主要部分
    def btnOk_click(self):
        csuper = CashContext(self.comboVar.get())
        totalPrice = csuper.get_result(float(self.txtPrice.get()) * float(self.txtNum.get()))
        self.total = self.total + totalPrice
        self.ibxList.insert('end', "单价:" + self.txtPrice.get() + " 数量:"
                            + self.txtNum.get() + " " + self.comboVar.get() + " 合计:%.2f" % (totalPrice) + "\n")
        self.iblResult.set("%.2f" % self.total)
        self.refresh()


if __name__ == '__main__':
    CashWindow()
"""
根据人的年龄,身高,体重进行排序
"""
from abc import ABCMeta, abstractmethod


class Person(object):
    """
    人类
    """

    def __init__(self, name, age, weight, height):
        self.name = name
        self.age = age
        self.weight = weight
        self.height = height

    def showMyself(self):
        print(f"{self.name}年龄 {self.age}岁, 体重 {self.weight}公斤, 身高 {self.height}米")


class ICompare(metaclass=ABCMeta):
    """
    比较算法
    """

    @abstractmethod
    def comparable(self, person1, person2):
        """
        如果person1 > person2 返回值 >0
        如果person1 == person2 返回值=0
        如果person1 < person2 返回值<0
        :param person1:
        :param person2:
        :return: value(person1 - person2)
        """
        raise NotImplementedError("Not implemented for ICompare")


class CompareByAge(ICompare):
    """
    通过年龄排序
    """

    def comparable(self, person1, person2):
        return person1.age - person2.age


class CompareByWeight(ICompare):
    """
    通过体重排序
    """

    def comparable(self, person1, person2):
        return person1.weight - person2.weight


class CompareByHeight(ICompare):
    """
    通过身高排序
    """

    def comparable(self, person1, person2):
        return person1.height - person2.height

class CompareByHeightAndWeight(ICompare):
    """
    通过身高和体重综合情况排序
    身高权重0.6, (体重/10)权重0.4
    """

    def comparable(self, person1, person2):
        value1 = person1.height*0.6 + person1.weight/10*0.4
        value2 = person2.height*0.6 + person2.weight/10*0.4
        return value1 - value2


class SortPerson(object):
    """
    上下文管理类
    """

    def __init__(self, compare):
        self.__compare = compare

    def sort(self, personList):
        """
        排序算法 冒泡排序
        :param personList: 人对象list
        :return:
        """
        personListCopy = personList[:]
        length = len(personListCopy)
        # 长度为1直接返回
        if length == 1:
            return personListCopy
        else:
            # 记录总共比较次数
            total_num = 0
            # 设置最后标志位,此标志位后的元素无需再进行比较
            last_flag = 0
            for i in range(length - 1):
                flag = False
                for j in range(length - last_flag - 1):
                    total_num += 1
                    if self.__compare.comparable(personListCopy[j], personListCopy[j + 1]) > 0:
                        personListCopy[j], personListCopy[j + 1] = personListCopy[j + 1], personListCopy[j]
                        last_flag = length - (j + 1)
                        flag = True
                if not flag:
                    break
            print('共比较了%d次。' % total_num)
            return personListCopy

def testSortPerson():
    personlist = [
        Person("Tony", 12, 54.5, 1.22),
        Person("Jack", 31, 74.5, 1.80),
        Person("Nick", 54, 44.5, 1.59),
        Person("Eric", 23, 62.0, 1.78),
        Person("Helen", 16, 45.7, 1.60)]
    print("排序前的结果:")
    for person in personlist:
        person.showMyself()

    ageSorter = SortPerson(CompareByAge())
    personlist_age = ageSorter.sort(personlist)
    # print("personlist改变没有:")
    # for person in personlist:
    #     person.showMyself()
    print("按照年龄排序后的结果:")
    for person in personlist_age:
        person.showMyself()

    hwSorter = SortPerson(CompareByHeightAndWeight())
    personlist_hw = hwSorter.sort(personlist)
    print("按照身高体重综合排序后的结果:")
    for person in personlist_hw:
        person.showMyself()


if __name__ == "__main__":
    testSortPerson()

适用场景

策略模式通过将一些易变的计算抽象为策略实体,通过多态,让实际调用者尽可能的不用感知这种变化。

实际应用

在导航应用中,有不同的路径规划算法,如针对步行的、骑行的、搭乘公共交通工具的、以及开车的等。主要导航类的主要工作是在地图上渲染出规划好的路径,并不会在意是由和算法生成的路径。此时可以将路径规划算法使用策略模式进行封装,方便与主要导航类的交互。

优点缺点

策略模式的优点有

  • 可以以相同的方式调用所有算法,减少了各种算法类与使用算法类之间的耦合。策略模式的Strategy类层次为Context类定义了一系列的可供重复使用的算法或行为,继承有助于析取这些算法中的公共功能。
  • 简化了单元测试。每个算法都有自己的类,可以通过自己的接口单独测试;
    符合“开放封闭原则”,无需对上下文进行修改就可以引入新的策略。

策略模式的缺点有

  • 不适合算法极少发生改变的场景,会使得程序整体过于复杂;
  • 要求客户端必须知晓策略间的不同,因为需要从中选择;

问题

  1. 为什么要使用抽象类?
    写成抽象类,这样别人看到你的代码,或你看到别人的代码,你就会注意抽象方法,而知道这个方法是在子类中实现的,所以,有个提示作用
    当我看到类是抽象的,我会很关心它的抽象方法。我知道它的子类一定会重写它,而且,我会去找到抽象类的引用。它一定会有多态性的体现。
    抽象类定义了一个算法家族,使得家族内的不同算法都遵从算法家族的接口及方法规范,从而可以实现算法间互相替换,且不会影响到使用算法的客户。

2 装饰模式

问题引入

一个人穿衣搭配,可以有无穷多种变化,不可能每种搭配都写一个子类。

模式定义

装饰模式(Decorator Pattern) 是指创建一个装饰类,来包装原有的类,从而实现动态地向一个现有的对象添加一些额外的职责,同时不改变其原有的结构。装饰模式比生成子类更为灵活

为什么要使用装饰模式

需要将所需功能按正确的顺序串联起来进行控制,此时可以考虑使用装饰模式。装饰模式比生成子类更为灵活。

解决方案

使用装饰模式来解决问题。

  1. 创建抽象的接口类Component,定义给对象动态添加职责的公共接口(在此例中,由于具体的接口只有一个,所以该步也可省略);
  2. 创建具体的接口Person(Concrete Component),继承于抽象接口类Component,同时:
    • 定义方法Show()用于显示装扮结果;
  3. 创建抽象的装饰类Finery(Decorator),继承于接口类Person(一般来说继承于抽象接口类Component,由于此例只有一个接口,故继承于具体接口类),同时:
    • 定义方法Decorate(component)用于进行装扮过程;
    • 覆写Show()具体装扮结果的显示;
  4. 创建系列具体的服饰类(Concrete Decorator),如Tshirts,BigTrouser等,继承于抽象装饰类Finery,实现具体的装饰对象,同时:
    • 覆写Show()具体装扮结果的显示。

代码实现

from abc import ABCMeta, abstractmethod

class Component(metaclass=ABCMeta):
    @abstractmethod
    def show(self):
        raise NotImplementedError

class Person(Component):
    def __init__(self, name=""):
        self._name = name
    def show(self):
        print("装扮的"+self._name)

# 服饰类(Decorator)
class Finery(Component):
    def __init__(self, person):
        self._person = person

    def show(self):
        self.decorate()
        self._person.show()

    @abstractmethod
    def decorate(self):
        raise NotImplementedError

# 具体服饰类(Concrete Decorator)
class TShirts(Finery):
    def __init__(self, person):
        super().__init__(person)

    def decorate(self):
        print("大T恤 ", end="")

class BigTrouser(Finery):
    def __init__(self, person):
        super().__init__(person)

    def decorate(self):
        print("垮裤 ", end="")


class Sneakers(Finery):
    def __init__(self, person):
        super().__init__(person)

    def decorate(self):
        print("破球鞋 ", end="")


class Suit(Finery):
    def __init__(self, person):
        super().__init__(person)

    def decorate(self):
        print("西装 ", end="")


class Tie(Finery):
    def __init__(self, person):
        super().__init__(person)

    def decorate(self):
        print("领带 ", end="")


class LeatherShoes(Finery):
    def __init__(self, person):
        super().__init__(person)

    def decorate(self):
        print("皮鞋 ", end="")


if __name__ == '__main__':
    xc = Person("小菜")
    print("第一种装扮:")
    dtx = TShirts(xc)
    kk = BigTrouser(dtx)
    pqx = Sneakers(kk)
    pqx.show()

    print("第二种装扮:")
    xz = Suit(xc)
    ld = Tie(xz)
    px = LeatherShoes(ld)
    px.show()

    print("第三种装扮:")
    pqx2 = Sneakers(xc)
    px2 = LeatherShoes(pqx2)
    kk2 = BigTrouser(px2)
    ld2 = Tie(kk2)
    ld2.show()
"""
装饰器模式附加的是处理的方法,动态的给一个类增加额外的功能,而不改变原有的代码.
如果是直接创建一个方法,只能添加参数,或者创建一系列的方法,不符合开闭原则
python中函数是一等公民了,可以将函数作为参数传递给另一个函数, 也可以将类
作为参数传递给你一个函数.
"""

from abc import ABCMeta, abstractmethod


class Component(metaclass=ABCMeta):

    @abstractmethod
    def wear(self):
        raise NotImplementedError


class Person(Component):
    def __init__(self, name):
        self._name = name

    def wear(self):
        print("着装: ")


# Person类的子类
class Engineer(Person):
    def __init__(self, name, skill):
        super().__init__(name)
        self._skill = skill

    def getSkill(self):
        return self._skill

    def wear(self):
        print(f"我是{self._name},我的职业是{self.getSkill()}工程师", end=", ")
        super().wear()


class Teacher(Person):
    def __init__(self, name, title):
        super().__init__(name)
        self._title = title

    def getTitle(self):
        return self._title

    def wear(self):
        print(f"我是{self._name},我的职业是{self.getTitle()}", end=", ")
        super().wear()


class ClothingDecorator(Component):
    def __init__(self, person):
        self._decorated = person

    def wear(self):
        self._decorated.wear()
        self.decorate()

    @abstractmethod
    def decorate(self):
        raise NotImplementedError


class CasualPantDecorator(ClothingDecorator):
    """
    休闲裤
    """

    def __init__(self, person):
        super().__init__(person)

    def decorate(self):
        print("一条卡其色休闲裤")


class BeltDecorator(ClothingDecorator):
    """
    腰带
    """

    def __init__(self, person):
        super().__init__(person)

    def decorate(self):
        print("一条银色针扣头的黑色腰带")


class LeatherShoesDecorator(ClothingDecorator):
    """
    皮鞋
    """

    def __init__(self, person):
        super().__init__(person)

    def decorate(self):
        print("一双黑色休闲皮鞋")


class KnittedSwearDecorator(ClothingDecorator):
    """
    毛衣
    """

    def __init__(self, person):
        super().__init__(person)

    def decorate(self):
        print("一件红色针织毛衣")


class WhiteShirtDecorator(ClothingDecorator):
    """
    衬衫
    """

    def __init__(self, person):
        super().__init__(person)

    def decorate(self):
        print("一件白色衬衫")


class GlassesDecorator(ClothingDecorator):
    """
    眼镜
    """

    def __init__(self, person):
        super().__init__(person)

    def decorate(self):
        print("一副方形黑框眼镜")


def test_clothing_decorator():
    print("工程师的装扮")
    tony = Engineer("Tony", "大数据")
    pant = CasualPantDecorator(tony)
    belt = BeltDecorator(pant)
    shoes = LeatherShoesDecorator(belt)
    shirt = WhiteShirtDecorator(shoes)
    sweater = KnittedSwearDecorator(shirt)
    glass = GlassesDecorator(sweater)
    glass.wear()
    print()
    print("老师的装扮")
    GlassesDecorator(WhiteShirtDecorator(LeatherShoesDecorator(Teacher("Thomas", "化学老师")))).wear()


if __name__ == "__main__":
    test_clothing_decorator()

适用场景

可以在不生成很多子类的情况下扩展类,适用于扩展类需求较多,而又不想引起子类膨胀的场景。

实际应用

  • 通知信息有多种渠道,如通过短信、微信、QQ、邮件等。不同的信息会采用不同的多种渠道组合进行通知,此时若对每一个组合都建立子类,会造成子类数量爆炸,可以考虑装饰器模式。

优点缺点

装饰模式的优点有:

  • 把类中的装饰功能从类中搬移去除,很好地简化了原有的类;
  • 有效地把类的核心职责和装饰功能区分开了,可以去除相关类中重复的装饰逻辑;
  • 装饰类和被装饰类可以独立发展,不会相互耦合;
  • 无需创建新子类即可实现对类功能的动态扩展;
  • 支持运行时添加或删除对象的功能;
  • 满足“单一职责原则”,可将实现许多不同行为的类拆分为多个较小的类。

装饰模式的缺点有:

  • 在封装器栈中删除特定封装器比较困难;
  • 较难实现行为不受到先后顺序影响的装饰;
  • 各装饰层的代码相对冗余。

python 中的特性,装饰器

python中函数作为一等公民,可以使用装饰器来对函数进行装饰,上面例子的代码如果用装饰器可以写成

"""
python 中函数是一等公民
"""

from abc import ABCMeta, abstractmethod


class Component(metaclass=ABCMeta):

    @abstractmethod
    def wear(self):
        raise NotImplementedError


class Person(Component):
    def __init__(self, name):
        self._name = name

    def wear(self):
        print("着装: ")


# Person类的子类
class Engineer(Person):
    def __init__(self, name, skill):
        super().__init__(name)
        self._skill = skill

    def getSkill(self):
        return self._skill

    def wear(self):
        print(f"我是{self._name},我的职业是{self.getSkill()}工程师", end=", ")
        super().wear()


class Teacher(Person):
    def __init__(self, name, title):
        super().__init__(name)
        self._title = title

    def getTitle(self):
        return self._title

    def wear(self):
        print(f"我是{self._name},我的职业是{self.getTitle()}", end=", ")
        super().wear()


def casualPantDecorator(func):
    def wrapper(*args, **kwargs):
        func(*args, **kwargs)
        print("一条卡其色休闲裤")

    return wrapper


def beltDecorator(func):
    def wrapper(*args, **kwargs):
        func(*args, **kwargs)
        print("一条银色针扣头的黑色腰带")

    return wrapper


def leatherShoesDecorator(func):
    def wrapper(*args, **kwargs):
        func(*args, **kwargs)
        print("一双黑色休闲皮鞋")

    return wrapper


def test_clothing_decorator():
    print("工程师的装扮")
    tony = Engineer("Tony", "大数据")
    pant = casualPantDecorator(tony.wear)
    belt = beltDecorator(pant)
    shoes = leatherShoesDecorator(belt)
    shoes()


if __name__ == "__main__":
    test_clothing_decorator()


策略模式和装饰模式比较

  • 功能上: 策略模式更倾向是N选1的模式,也即根据条件选择相应的算法,但各种算法是互斥的,装饰模式是在主体逻辑的基础上的附加逻辑.
  • 代码结构上: 策略模式是不需要与组件有相同的接口的,装饰模式需要装饰器与组件有相同的接口.

3 代理模式

问题引入

A男想追B女,但是A和B没有直接接触过,每次送礼物都是通过B的室友C,这里的C的行为就类似于代理。

模式定义

代理模式(Proxy Pattern)是指实现一个类代表另一个类的功能,为其他对象提供一种代理以控制对这个对象的访问。

为什么要使用代理模式

一个客户端或服务端的功能单一,通过代理可以增加功能,扩展用途。
无需对客户端或者服务端进行修改就可以创建新的代理。
代理可以理解为实体的影子。

解决方案

使用代理模式来解决这一问题。

  1. 创建送礼物的抽象类IGiveGift,定义追求者和代理的共用接口:
    • 送玩具方法GiveDolls();
    • 送花方法GiveFlowers();
    • 送巧克力方法GiveChocolate()。
  2. 创建追求者Pursuit,定义需要代理的真正实体,继承于抽象类IGiveGift:
    • 覆写类初始化方法,记录被追求者姓名;
    • 覆写送玩具、送花、送巧克力方法,具体送礼操作。
  3. 创建代理Proxy,保存追求者实体的一个引用,使得代理可以访问实体,继承于抽象类IGiveGift,实现对实体的替代:
    • 覆写类初始化方法,初始化的同时初始化一个追求者Pursuit对象;
    • 覆写送玩具、送花、送巧克力方法,在每一个送礼方法下调用追求者Pursuit的具体送礼操作

代码实现

from abc import ABCMeta, abstractmethod


class SchoolGirl(object):
    def __init__(self, name):
        self.__name = name

    def get_name(self):
        return self.__name


class IGiveGift(metaclass=ABCMeta):

    @abstractmethod
    def give_dolls(self):
        raise NotImplementedError

    @abstractmethod
    def give_flowers(self):
        raise NotImplementedError

    @abstractmethod
    def give_chocolate(self):
        raise NotImplementedError


class Pursuit(IGiveGift):
    __mm = None

    def __init__(self, mm: SchoolGirl):
        self.__mm = mm

    def give_dolls(self):
        print(f"送{self.__mm.get_name()}洋娃娃")

    def give_flowers(self):
        print(f"送{self.__mm.get_name()}鲜花")

    def give_chocolate(self):
        print(f"送{self.__mm.get_name()}巧克力")


class Proxy(IGiveGift):
    def __init__(self, mm: SchoolGirl):
        self.gg = Pursuit(mm)

    def give_dolls(self):
        self.gg.give_dolls()

    def give_flowers(self):
        self.gg.give_flowers()

    def give_chocolate(self):
        self.gg.give_chocolate()


if __name__ == '__main__':
    jiaojiao = SchoolGirl("李娇娇")

    daili = Proxy(jiaojiao)
    daili.give_dolls()
    daili.give_flowers()
    daili.give_chocolate()

"""
邻居作为代理帮助收快递

"""

from abc import ABCMeta, abstractmethod


class Subject(metaclass=ABCMeta):
    """
    抽象类,
    """

    def __init__(self, name):
        self.__name = name

    def getName(self):
        return self.__name

    @abstractmethod
    def request(self, content=""):
        raise NotImplementedError("NotImplementedError")


class TonyReception(Subject):
    """
    Tony接收
    """

    def __init__(self, name, phoneNum):
        super().__init__(name)
        self.__phoneNum = phoneNum

    def getPhoneNum(self):
        return self.__phoneNum

    def request(self, content):
        print(f"货物主人:{self.getName()}, 手机号:{self.getPhoneNum()}")
        print(f"接收到一个包裹,里面是{content}")


class WendyReception(Subject):
    def __init__(self, name, subject):
        super().__init__(name)
        self._realSubject = subject

    def preRequest(self):
        print(f"我是{self._realSubject.getName()}的朋友,我来帮他代收快递.")

    def afterRequest(self):
        print(f"代收人:{self.getName()}")

    def request(self, content):
        self.preRequest()
        if self._realSubject is not None:
            self._realSubject.request(content)
        self.afterRequest()

def testProxy():
    tony = TonyReception("Tony","18112345678")
    tony.request("雪地靴")

    wendy = WendyReception("wendy",tony)
    wendy.request("雪地靴")

if __name__ == "__main__":
    testProxy()

适用场景

不方便直接访问对象时,为不宜直接访问的对象提供一个访问层。

使用代理模式的方式分为以下几种:

  • 本地执行远程服务(远程代理):适用于服务对象位于远程服务器上的情形,可以为一个对象在不同的地址空间提供局部代表。
  • 延迟初始化(虚拟代理):如果你有一个偶尔使用的重量级服务对象,一直保持该对象运行会消耗系统资源时,可使用代理模式。
  • 访问控制(保护代理/安全代理):如果只希望特定客户端使用服务对象,对象可以是操作系统中的重要部分,而客户端则是各种已启动程序,可使用代理模式。
  • 记录日志请求(日志记录代理):适用于需要保存对于服务对象的请求历史记录时。
  • 缓存请求结果(缓存代理):适用于需要缓存客户请求结果并对缓存生命周期进行管理时,特别是返回结果体积非常大时。
  • 智能指引:调用真实对象时,代理处理另外一些事,可在没有客户端使用某个重量级对象时,立刻销毁该对象。

实际应用

  • 信用卡是银行账户的代理,而银行账户则是一大捆现金的代理。它们都可以实现相同的支付功能。
  • windows里的快捷方式。
  • 客户端对数据库的查询有时要消耗大量系统资源,常在有需要时才创建(延迟初始化),这会带来代码的大量重复。可以创建代理,让代理伪装成数据库对象,在客户端或实际数据库对象不知情的情况下处理延迟初始化和缓存查询结果的工作。

优点缺点

模式优点包括:

  • 引入代理后,职责清晰;
  • 引入代理后,可扩展多种用途,如:
    • 远程代理可以隐藏一个对象存在于不同地址空间的事实。
    • 虚拟代理可以存放实例化时间很长的真实对象。
  • 符合“开放封闭原则”,无需对服务器或客户端进行修改就创建新的代理。

模式缺点包括:

  • 代码可能变得复杂,因为需要新建许多类;
  • 服务响应可能会延迟。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值