# Structural Patterns

Adapter

内容：将一个类的接口转换成客户希望的另一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

1.适用场景：想使用一个已经存在的类，而他的接口不符合要求, 两种实现方式：

* 类适配器：使用多继承

```python
# 当我们需要改动部分的代码很少的时候，我们直接多继承+复写方法即可
from abc import ABCMeta,abstractclassmethod

class Payment(metaclass=ABCMeta):
    @abstractclassmethod
    def pay(self,money):
        pass

class Alipay(Payment):
    def pay(self,money):
        print("阿里支付了{}元".format(money))

class Weixinpay(Payment):
    def pay(self,money):
        print("微信支付了{}元".format(money))

class Bankpay:
    def cost(self,money):
        print("银行卡支付{}元".format(money))

class NewBankPay(Payment,Bankpay):
    def pay(self,money):
        self.cost(money)

nb = NewBankPay()
nb.pay(100)
```

* 对象适配器：使用组合

```python
from abc import ABCMeta,abstractclassmethod

class Payment(metaclass=ABCMeta):
    @abstractclassmethod
    def pay(self,money):
        pass

class Alipay(Payment):
    def pay(self,money):
        print("阿里支付了{}元".format(money))

class Weixinpay(Payment):
    def pay(self,money):
        print("微信支付了{}元".format(money))

# 当存在多个需要进行适配的代码的时候(对象适配器)
class Bankpay:
    def cost(self,money):
        print("银行卡支付{}元".format(money))

class Applepay:
    def cost(self,money):
        print("苹果支付{}元".format(money))

class PaymentAdapter(Payment):
    def __init__(self,payment):
        self.payment = payment

    def pay(self,money):
        self.payment.cost(money)

nb = PaymentAdapter(Bankpay())
nb.pay(100)
```

```python
from typing import Callable, TypeVar

T = TypeVar("T")


class Dog:
    def __init__(self) -> None:
        self.name = "Dog"

    def bark(self) -> str:
        return "woof!"


class Cat:
    def __init__(self) -> None:
        self.name = "Cat"

    def meow(self) -> str:
        return "meow!"


class Human:
    def __init__(self) -> None:
        self.name = "Human"

    def speak(self) -> str:
        return "'hello'"


class Car:
    def __init__(self) -> None:
        self.name = "Car"

    def make_noise(self, octane_level: int) -> str:
        return f"vroom{'!' * octane_level}"


class Adapter:
    """Adapts an object by replacing methods.
    Usage
    ------
    dog = Dog()
    dog = Adapter(dog, make_noise=dog.bark)
    """

    def __init__(self, obj: T, **adapted_methods: Callable):
        """We set the adapted methods in the object's dict."""
        self.obj = obj
        self.__dict__.update(adapted_methods)

    def __getattr__(self, attr):
        """All non-adapted calls are passed to the object."""
        return getattr(self.obj, attr)

    def original_dict(self):
        """Print original object dict."""
        return self.obj.__dict__


def main():
    """
    >>> objects = []
    >>> dog = Dog()
    >>> print(dog.__dict__)
    {'name': 'Dog'}
    >>> objects.append(Adapter(dog, make_noise=dog.bark))
    >>> objects[0].__dict__['obj'], objects[0].__dict__['make_noise']
    (<...Dog object at 0x...>, <bound method Dog.bark of <...Dog object at 0x...>>)
    >>> print(objects[0].original_dict())
    {'name': 'Dog'}
    >>> cat = Cat()
    >>> objects.append(Adapter(cat, make_noise=cat.meow))
    >>> human = Human()
    >>> objects.append(Adapter(human, make_noise=human.speak))
    >>> car = Car()
    >>> objects.append(Adapter(car, make_noise=lambda: car.make_noise(3)))
    >>> for obj in objects:
    ...    print("A {0} goes {1}".format(obj.name, obj.make_noise()))
    A Dog goes woof!
    A Cat goes meow!
    A Human goes 'hello'
    A Car goes vroom!!!
    """


if __name__ == "__main__":
    import doctest

    doctest.testmod(optionflags=doctest.ELLIPSIS)t
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://zeliang-yao.gitbook.io/my-note-zeliang-yao/useful/design-patterns/structural-patterns.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
