目录
一、试画出适配器模式实例的结构图和实现代码,并对模式进行分析
三、使用Java语言实现一个双向适配器实例,使得猫可以学狗叫,狗可以学猫抓老鼠,绘制相应类图并使用代码编程模拟
结构性模式(7种):【描述如何将类或对象结合在一起形成更大的结构】适配器模式、桥接模式、组合模式、装饰模式、外观模式、享元模式、代理模式
适配器模式:将一个类的接口转换成客户希望的另一个接口。适配器模式使得由于接口不兼容而不能一起工作的那些类可以一起工作。
适配器模式的实现方式:1.类适配器:使用多继承; 2.对象适配器:使用组合。
桥接模式:将一个事物的两个维度分离,使其都可以独立地变化。
一、试画出适配器模式实例的结构图和实现代码,并对模式进行分析
1.1 适配器模式结构图:
图1 类适配器的模式结构图
图2 对象适配器的模式结构图
适配器模式(Adapter Pattern):将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。适配器模式分为类结构型模式和对象结构型模式两种,前者类之间的耦合度比后者高,且要求程序员了解现有组件库中的相关组件的内部结构,所以应用相对较少些。
由图1和图2可知,适配器模式包含以下3个角色:
- 目标接口:当前系统业务所期待的接口,它可以是抽象类或接口;
- 适配者类:当前系统业务所期待的接口,它可以是抽象类或接口;
- 适配器类:它是一个转换器,通过继承或引用适配者的对象,把适配者接口转换成目标接口,让客户按目标接口的格式访问适配者。
1.2 适配器模式的实现(Java)
类适配器代码如下:
package adapter;
//目标接口
interface Target{
public void request();
}
//适配者接口
class Adaptee
{
public void specificRequest()
{
System.out.println("适配者中的业务代码被调用!");
}
}
//类适配器类
class ClassAdapter extends Adaptee implements Target
{
public void request()
{
specificRequest();
}
}
//客户端代码
public class ClassAdapterTest
{
public static void main(String[] args)
{
System.out.println("类适配器模式测试:");
Target target = new ClassAdapter();
target.request();
}
}
对象适配器模式中的“目标接口”和“适配者类”的代码同类适配器模式一样,只要修改适配器类和客户端的代码即可:
package adapter;
//对象适配器类
class ObjectAdapter implements Target
{
private Adaptee adaptee;
public ObjectAdapter(Adaptee adaptee)
{
this.adaptee=adaptee;
}
public void request()
{
adaptee.specificRequest();
}
}
//客户端代码
public class ObjectAdapterTest
{
public static void main(String[] args)
{
System.out.println("对象适配器模式测试:");
Adaptee adaptee = new Adaptee();
Target target = new ObjectAdapter(adaptee);
target.request();
}
}
1.3 适配器模式的优缺点
适配器模式应用场景在于以前开发的系统存在满足新系统功能需求的类,但其接口同新系统的接口不一致时,或者是使用第三方提供的组件,但组件接口定义和自己要求的接口定义不同。
优点:
- 客户端通过适配器可以透明地调用目标接口;
- 复用了现存的类,程序员不需要修改原有代码而重用现有的适配者类;
- 将目标类和适配者类解耦,解决了目标类和适配者类接口不一致的问题。
缺点:
- 对类适配器来说,更换适配器的实现过程比较复杂。
1.4 适配器模式实现(Python)
#!/usr/bin/env python
# _*_ coding: utf-8 _*_
# @Time :
# @Author :
# @Version:V 0.1
# @File : 适配器模式.py
# @desc : 将一个类的接口转换成客户希望的另一个接口
from abc import ABCMeta, abstractmethod
class Payment(metaclass=ABCMeta):
# abstarct class
@abstractmethod
def pay(self, money):
pass
class Alipay(Payment):
def pay(self, money):
print("支付宝支付{}元。".format(money))
class WechatPay(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 NewbankPay(Payment, BankPay):
# def pay(self, money):
# self.cost(money)
# 另外一种适配器写法(对象适配器)
class PaymentAdapter(Payment):
def __init__(self, payment):
self.payment = payment
def pay(self, money):
self.payment.cost(money)
p = PaymentAdapter(ApplePay())
p.pay(100)
二、试画出桥接模式实例的结构图和实现代码,并对模式进行分析
2.1桥接模式结构图
图3 桥接模式的模式结构图
将抽象与实现分离,使它们可以独立变化。它是用组合关系代替继承关系来实现,从而降低了抽象和实现这两个可变维度的耦合度。
由图3可知,桥接模式包含以下4个角色:
- 抽象化角色:定义抽象类,并包含一个对实现化对象的引用;
- 扩展抽象化角色:是抽象化角色的子类,实现父类中的业务方法,并通过组合关系调用实现化角色中的业务方法;
- 实现化角色:定义实现化角色的接口,供扩展抽象化角色调用;
- 具体实现化角色:给出实现化角色接口的具体实现。
2.2 桥接模式的实现(Java)
package bridge;
public class BridgeTest
{
public static void main(String[] args)
{
Implementor imple=new ConcreteImplementorA();
Abstraction abs=new RefinedAbstraction(imple);
abs.Operation();
}
}
//实现化角色
interface Implementor{
public void OperationImpl();
}
//具体实现化角色
class ConcreteImplementorA implements Implementor
{
public void OperationImpl()
{
System.out.println("具体实现化(Concrete Implementor)角色被访问" );
}
}
//抽象化角色
abstract class Abstraction
{
protected Implementor imple;
protected Abstraction(Implementor imple)
{
this.imple=imple;
}
public abstract void Operation();
}
//扩展抽象化角色
class RefinedAbstraction extends Abstraction
{
protected RefinedAbstraction(Implementor imple)
{
super(imple);
}
public void Operation()
{
System.out.println("扩展抽象化(Refined Abstraction)角色被访问" );
imple.OperationImpl();
}
}
2.3 桥接模式的优缺点
建造者模式的应用场景是当一个类存在两个独立变化的维度,且这两个维度都需要进行扩展时或者当一个系统不希望使用继承或因为多层次继承导致系统类的个数急剧增加时以及当一个系统需要在构件的抽象化角色和具体化角色之间增加更多的灵活性。
有时桥接(Bridge)模式可与适配器模式联合使用。当桥接(Bridge)模式的实现化角色的接口与现有类的接口不一致时,可以在二者中间定义一个适配器将二者连接起来
桥接模式特点:
- 抽象化:将对象的共同性质抽取出来形成类的过程就是抽象化;
- 实现化:针对抽象化给出的具体实现,就是实现化。实现化产生的对象比抽象化更具体,是对抽象化事物的进一步具体化的产物;
- 脱耦:将抽象化和实现化之间的耦合解脱开,或者说是将他们之间的强关联改成弱关联,将两个角色之间的继承关系改为关联关系。
2.4 桥接模式实现(Python)
#!/usr/bin/env python
# _*_ coding: utf-8 _*_
# @Time :
# @Author :
# @Version:V 0.1
# @File : 桥接模式.py
# @desc : 将一个事物的两个维度分离,使其都可以独立地变化
from abc import ABCMeta, abstractmethod
class Shape(metaclass=ABCMeta):
def __init__(self, color):
self.color = color
@abstractmethod
def draw(self):
pass
class Color(metaclass=ABCMeta):
@abstractmethod
def paint(self, shape):
pass
class Rectangle(Shape):
name = "矩形"
def draw(self):
self.color.paint(self)
class Circle(Shape):
name = "圆形"
def draw(self):
self.color.paint(self)
class Red(Color):
def paint(self, shape):
print("红色的{}".format(shape.name))
class Green(Color):
def paint(self, shape):
print("绿色的{}".format(shape.name))
shape = Rectangle(Red())
shape.draw()
shape2 = Circle(Green())
shape2.draw()
三、使用Java语言实现一个双向适配器实例,使得猫可以学狗叫,狗可以学猫抓老鼠,绘制相应类图并使用代码编程模拟
3.1 双向适配器模式结构图
图4 双向适配器的模式结构图
3.2 双向适配器程序实现
public interface CatTarget {
public abstract void catchMouse();
}
public class ConcreteCatTarget implements CatTarget {
@Override
public void catchMouse() {
System.out.println("抓老鼠!");
}
}
public interface DogAdaptee {
public abstract void cry();
}
public class ConcreteDogAdaptee implements DogAdaptee {
@Override
public void cry() {
System.out.println("汪汪汪汪!");
}
}
public class Adapter implements CatTarget,DogAdaptee {
private CatTarget catTarget;
private DogAdaptee dogAdaptee;
public Adapter() {
}
public void setCatTarget(CatTarget catTarget) {
this.catTarget = catTarget;
}
public void setDogAdaptee(DogAdaptee dogAdaptee) {
this.dogAdaptee = dogAdaptee;
}
//即目标类调用适配者中的方法
public void catchMouse() {
System.out.print("猫学狗叫");
dogAdaptee.cry();
}
//即适配者调用目标类中的方法
public void cry(){
System.out.print("狗学猫抓老鼠");
catTarget.catchMouse();
}
}
public class Client {
public static void main(String[] args) {
//适配器
Adapter adapter = (Adapter) XMLUtils.getBean("adapterPattern");
//目标类通过适配器调用适配者方法
CatTarget concreteCatTarget = (ConcreteCatTarget) XMLUtils.getBean("adapterPatternTarger");
adapter.setCatTarget(concreteCatTarget);
adapter.cry();
//适配者通过适配器调用目标类方法
DogAdaptee concreteDogAdaptee = (ConcreteDogAdaptee) XMLUtils.getBean("adapterPatternAdaptee");
adapter.setDogAdaptee(concreteDogAdaptee);
adapter.catchMouse();
}
}