一、原型模式(Prototype)
1、概述
1、定义:
用原型实例指定了要创建对象的种类,并且通过拷贝这些原型,创建新的对象。原型模式是一种创建型设计模式,允许一个对象再创建另外一个可定制的对象, 无需知道如何创建的细节。
2、工作原理:
通过将一个原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求原型对象拷贝它们自己来实施创建,即对象.clone()
。形象的理解:孙大圣拔出猴毛, 变出其它孙大圣。
3、在Spring框架中创建Bean的时候使用到原型模式。
4、源对象给外部提供一个克隆对象进行使用,克隆对象有任何修改,都不会影响源对象
2、主要角色
1、抽象原型类:规定了具体原型对象必须实现的接口。
2、具体原型类:实现抽象原型类的clone()
方法,它是可以被复制的对象。
3、访问类:使用具体原型类中的clone()
方法来复制新的对象。
3、传统方式完成复制对象
@Data
@AllArgsConstructor
public class Sheep {
private String name;
private Integer age;
private String color;
}
public class Test {
public static void main(String[] args) {
Sheep sheep = new Sheep("克隆羊",1,"白色");
Sheep sheep1 = new Sheep(sheep.getName(), sheep.getAge(), sheep.getColor());
Sheep sheep2 = new Sheep(sheep.getName(), sheep.getAge(), sheep.getColor());
Sheep sheep3 = new Sheep(sheep.getName(), sheep.getAge(), sheep.getColor());
Sheep sheep4 = new Sheep(sheep.getName(), sheep.getAge(), sheep.getColor());
System.out.println(sheep);
System.out.println(sheep1);
System.out.println(sheep2);
System.out.println(sheep3);
System.out.println(sheep4);
}
}
/**
* 运行结果
*/
Sheep(name=克隆羊, age=1, color=白色)
Sheep(name=克隆羊, age=1, color=白色)
Sheep(name=克隆羊, age=1, color=白色)
Sheep(name=克隆羊, age=1, color=白色)
Sheep(name=克隆羊, age=1, color=白色)
1、优缺点说明
:
-
优点是比较好理解,简单易操作。
-
在创建新的对象时,总是需要重新获取原始对象的属性,如果创建的对象比较复杂时,效率较低。
-
总是需要重新初始化对象,而不是动态地获得对象运行时的状态,不够灵活。
2、改进的方法:
-
Java中Object类是所有类的基类,Object类提供了一个clone()方法,该方法可以将一个Java对象复制一份,但是需要实现clone的Java类必须要实现一个接口Cloneable, 该接口表示该类能够复制且具有复制的能力。
4、原型模式实现
/**
* 原型类
*/
@Data
@AllArgsConstructor
public class Sheep implements Cloneable {
private String name;
private Integer age;
private String color;
/**
* 克隆该实例使用默认的clone方法来完成
* @return
*/
@Override
protected Object clone() {
Sheep sheep = null;
try {
sheep = (Sheep)super.clone();
} catch (CloneNotSupportedException e) {
System.out.println(e.getMessage());
}
return sheep;
}
}
/**
* 客户端调用类
*/
public class Test {
public static void main(String[] args) {
Sheep sheep = new Sheep("克隆羊",1,"白色");
System.out.println("原型模式完成对象的创建");
Sheep sheep1 = (Sheep) sheep.clone();
Sheep sheep2 = (Sheep) sheep.clone();
Sheep sheep3 = (Sheep) sheep.clone();
Sheep sheep4 = (Sheep) sheep.clone();
System.out.println(sheep);
System.out.println(sheep1);
System.out.println(sheep2);
System.out.println(sheep3);
System.out.println(sheep4);
}
}
/**
* 运行结果:
* 原型模式完成对象的创建
* Sheep(name=克隆羊, age=1, color=白色)
* Sheep(name=克隆羊, age=1, color=白色)
* Sheep(name=克隆羊, age=1, color=白色)
* Sheep(name=克隆羊, age=1, color=白色)
* Sheep(name=克隆羊, age=1, color=白色)
*/
5、浅拷贝
1、对于数据类型是基本数据类型的成员变量,浅拷贝会直接进行值传递,也就是将该属性值复制一份给新的对象
。
2、对于数据类型是引用数据类型的成员变量,比如说成员变量是某个数组、某个类的对象等,那么浅拷贝会进行引用传递,也就是只是将该成员变量的引用值(内存地址)复制一份给新的对象。因为实际上两个对象的该成员变量都指向同一个实例。在这种情况下,在一个对象中修改该成员变量会影响到另一个对象的该成员变量值
。
3、上述示例就是浅拷贝,浅拷贝是使用默认的 clone()
方法来实现。
6、深拷贝
1、复制对象的所有基本数据类型的成员变量值。
2、为所有引用数据类型的成员变量申请存储空间,并复制每个引用数据类型成员变量所引用的对象,直到该对象可达到的所有对象。也就是说,对象进行深拷贝要对整个对象进行拷贝。
3、深拷贝要两种实现方式:
-
重写clone方法来实现深拷贝。
-
通过对象序列化实现深拷贝(推荐使用)。
7、重写clone方法来实现深拷贝
public class DeepCloneableTarget implements Cloneable, Serializable {
private static final long serialVersionUID = 1L;
private String cloneName;
private String cloneClass;
public DeepCloneableTarget(String cloneName, String cloneClass) {
this.cloneName = cloneName;
this.cloneClass = cloneClass;
}
/**
* 因为该类的属性都是string,因此使用默认的clone完成即可
* @return
* @throws CloneNotSupportedException
*/
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public class DeepProtoType implements Cloneable, Serializable {
private String name;
/**
* 引用类型
*/
private DeepCloneableTarget deepCloneableTarget;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public DeepCloneableTarget getDeepCloneableTarget() {
return deepCloneableTarget;
}
public void setDeepCloneableTarget(DeepCloneableTarget deepCloneableTarget) {
this.deepCloneableTarget = deepCloneableTarget;
}
/**
* 重写clone方法实现深拷贝
* @return
* @throws CloneNotSupportedException
*/
@Override
protected Object clone() throws CloneNotSupportedException {
Object deep = null;
//完成对基本数据类型(属性)和String的克隆
deep = super.clone();
//对引用类型的属性,进行单独处理
DeepProtoType deepProtoType = (DeepProtoType) deep;
deepProtoType.deepCloneableTarget = (DeepCloneableTarget) deepCloneableTarget.clone();
return deepProtoType;
}
}
public class Test {
public static void main(String[] args) throws Exception {
DeepProtoType p1 = new DeepProtoType();
p1.setName("重写clone");
p1.setDeepCloneableTarget(new DeepCloneableTarget("大牛","小牛"));
//调用深拷贝
DeepProtoType p2 = (DeepProtoType) p1.clone();
System.out.println("p1.name = " + p1.getName() + ",p1 = " + p1.hashCode() + ",p1.deepCloneableTarget = " + p1.getDeepCloneableTarget().hashCode());
System.out.println("p2.name = " + p2.getName() + ",p2 = " + p2.hashCode() + ",p2.deepCloneableTarget = " + p2.getDeepCloneableTarget().hashCode());
}
}
/**
* 运行结果:
* p1.name = 重写clone,p1 = 1956725890,p1.deepCloneableTarget = 356573597
* p2.name = 重写clone,p2 = 1735600054,p2.deepCloneableTarget = 21685669
*/
注意:如果在类上加了@Data注解,那么此类实例化的对象,如果没有为属性设置值,则两个实例化对象的hashCode()是相等的
8、通过对象序列化实现深拷贝
public class DeepProtoType implements Cloneable, Serializable {
private String name;
/**
* 引用类型
*/
private DeepCloneableTarget deepCloneableTarget;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public DeepCloneableTarget getDeepCloneableTarget() {
return deepCloneableTarget;
}
public void setDeepCloneableTarget(DeepCloneableTarget deepCloneableTarget) {
this.deepCloneableTarget = deepCloneableTarget;
}
/**
* 对象序列化实现深拷贝
* @return
* @throws CloneNotSupportedException
*/
@Override
protected Object clone() throws CloneNotSupportedException {
//创建流对象
ByteArrayOutputStream bos = null;
ObjectOutputStream oos = null;
ByteArrayInputStream bis = null;
ObjectInputStream ois = null;
try {
//序列化
bos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(bos);
//将当前这个对象以对象流的方式输出
oos.writeObject(this);
//反序列化
bis = new ByteArrayInputStream(bos.toByteArray());
ois = new ObjectInputStream(bis);
DeepProtoType deepProtoType = (DeepProtoType) ois.readObject();
return deepProtoType;
} catch (Exception e) {
e.printStackTrace();
return null;
} finally {
try {
bos.close();
oos.close();
bis.close();
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
9、优缺点说明
1、优点:
-
创建新的对象比较复杂时,可以利用原型模式简化对象的创建过程,同时也能够提高效率。
-
不用重新初始化对象,而是动态地获得对象运行时的状态。
-
如果原始对象发生变化(增加或者减少属性),其它克隆对象的也会发生相应的变化, 无需修改代码。
2、缺点:
-
需要为每一个类配备一个克隆方法,这对全新的类来说不是很难,但对已有 的类进行改造时,需要修改其源代码,违背了ocp(开闭)原则。
-
当实现深克隆时,需要编写较为复杂的代码,而且当对象之间存在多重嵌套引用时,为了实现深克隆,每一层对象对应的类都必须支持深克隆,实现起来会比较麻烦。因此,深克隆、浅克隆需要运用得当。
二、建造者模式
1、概述
1、定义:
建造者模式(Builder Pattern) 又叫生成器模式,是一种对象构建模式。它可以将复杂对象的建造过程抽象出来(抽象类别),使这个抽象过程的不同实现方法可以构造出不同表现(属性)的对象。它是将一个复杂的对象分解为多个简单的对象,然后一步一步构建而成。它将变与不变相分离,即产品的组成部分是不变的,但每一部分是可以灵活选择的。
2、建造者(Builder)模式和工厂模式的关注点不同:
建造者模式注重零部件的组装过程,而工厂方法模式更注重零部件的创建过程,但两者可以结合使用。(比如建房:需要打桩、砌墙、封顶)。
2、主要角色
1、产品角色(Product):它是包含多个组成部件的复杂对象,由具体建造者来创建其各个零部件。
2、抽象建造者(Builder):它是一个包含创建产品各个子部件的抽象方法的接口或抽象类,通常还包含一个返回复杂产品的方法。
3、具体建造者(Concrete Builder):实现抽象建造者的接口,完成复杂产品的各个部件的具体创建方法。
4、指挥者(Director):它调用建造者对象中的部件构造与装配方法完成复杂对象的创建,在指挥者中不涉及具体产品的信息。
3、建造者模式实现
/**
* 产品类
*/
@Data
public class House {
private String baise;
private String wall;
private String roofed;
}
/**
* 抽象建造者类
*/
public abstract class HouseBuilder {
protected House house = new House();
public abstract void buildBasic();
public abstract void buildWalls();
public abstract void roofed();
/**
* 返回产品对象
* @return
*/
public House getResult() {
return house;
}
}
/**
* 具体建造者类
*/
public class CommonHouse extends HouseBuilder {
@Override
public void buildBasic() {
house.setBaise("打地基");
}
@Override
public void buildWalls() {
house.setWall("砌墙");
}
@Override
public void roofed() {
house.setRoofed("封顶");
}
}
/**
* 指挥者,指定创建流程,返回产品
*/
public class HouseDirector {
private HouseBuilder houseBuilder;
/**
* 构造器传入houseBuilder
* @param houseBuilder
*/
public HouseDirector(HouseBuilder houseBuilder) {
this.houseBuilder = houseBuilder;
}
/**
* 产品构建与组装方法
* @return
*/
public House constructHouse() {
houseBuilder.buildBasic();
houseBuilder.buildWalls();
houseBuilder.roofed();
return houseBuilder.getResult();
}
}
/**
* 客户端调用类
*/
public class Test {
public static void main(String[] args) {
// 创建具体建造者
CommonHouse commonHouse = new CommonHouse();
// 创建指挥
HouseDirector houseDirector = new HouseDirector(commonHouse);
// 调用构建方法
House house = houseDirector.constructHouse();
System.out.println(house);
}
}
/**
* 运行结果:
* House(baise=打地基, wall=砌墙, roofed=封顶)
*/
4、建造者模式在JDK的应用
1、java.lang.StringBuilder中的建造者模式
:
-
Appendable接口定义了多个append方法(抽象方法),即Appendable为抽象建造者, 定义了抽象方法。
-
AbstractStringBuilder实现了Appendable接口方法,这里的AbstractStringBuilder已经是建造者,只是不能实例化。
-
StringBuilder即充当了指挥者角色,同时充当了具体的建造者,建造方法的实现是由AbstractStringBuilder完成,而StringBuilder继承了AbstractStringBuilder 。
5、优缺点说明
1、优点:
-
封装性好,构建和表示分离。
-
扩展性好,各个具体的建造者相互独立,有利于系统的解耦。
-
客户端不必知道产品内部组成的细节,建造者可以对创建过程逐步细化,而不对其它模块产生任何影响,便于控制细节风险。
2、缺点:
-
建造者模式所创建的产品一般具有较多的共同点,产品的组成部分相似,如果产品之间的差异性很大,则不适合使用建造者模式,这限制了其使用范围。
-
如果产品的内部变化复杂,如果产品内部发生变化,则建造者也要同步修改,后期维护成本较大。
三、适配器模式
1、概述
1、定义:
适配器模式(Adapter Pattern)将某个类的接口转换成客户端期望的另一个接口表示,主的目的是兼容性,让原本因接口不匹配不能一起工作的两个类可以协同工作。其别名为包装器(Wrapper)。
2、分类:
-
类适配器模式。
-
对象适配器模式。
-
接口适配器模式。
-
注意:类适配器模式的耦合度比对象的高
。
3、工作原理:
将一个类的接口转换为另一种接口,让原本接口不兼容的类可以兼容
。从用户角度看不到被适配者,是解耦的,用户调用适配器转化出来的目标接口方法,适配器再调用被适配者的相关接口方法,用户收到反馈结果,感觉只是和目标接口交互。
2、主要角色
1、目标接口(Target):可以是抽象类或接口,当前系统业务期望直接用的接口。
2、被适配者(Adaptee):它是被访问和适配的现存组件库中的组件接口。
3、适配器(Adapter):它是一个转换器,通过继承或引用被适配者的对象,把适配者接口转换成目标接口,让系统按目标接口的格式访问被适配者。
3、类适配器模式实现
Adapter类通过继承Adaptee类,实现Target类接口完成适配。
/**
* 被适配的类
*/
public class Adaptee {
public int outPut220v() {
int num = 220;
System.out.println("原始电压为" + num + "伏特");
return num;
}
}
/**
* 目标接口
*/
public interface Target {
public int outPut5v();
}
/**
* 类适配器
*/
public class ClassAdapter extends Adaptee implements Target {
@Override
public int outPut5v() {
//获取220V电压
int outPut220v = outPut220v();
//转换成目标接口所需要的
return outPut220v / 44;
}
}
/**
* 客户端调用类
*/
public class Test {
public static void main(String[] args) {
System.out.println("类适配器模式");
Target target = new ClassAdapter();
System.out.println("手机能接受电压为" + target.outPut5v() + "伏特");
}
}
/**
* 运行结果:
* 类适配器模式
* 原始电压为220伏特
* 手机能接受电压为5伏特
*/
1、优缺点说明:
-
Java是单继承机制,所以类适配器需要继承Adaptee类这一点算是一个缺点,因为这要求Target必须是接口,有一定局限性。
-
Adaptee类的方法在Adapter中都会暴露出来,也增加了使用的成本。
-
由于其继承了Adaptee类,所以它可以根据需求重写Adaptee类的方法,使得Adapter的灵活性增强了。
4、对象适配器模式实现
1、基本思路和类的适配器模式相同,只不过实现方式不同,只是将Adapter类作修改,不是继承Adaptee类,而是持有Adaptee类的实例,以解决兼容性的问题。 即:持有Adaptee类,实现Target类接口,完成Adaptee -> Target的适配。
2、根据“合成复用原则”,在系统中尽量使用组合关系来替代继承关系。
3、对象适配器模式是适配器模式常用的一种。
/**
* 被适配的类
*/
public class Adaptee {
public int outPut220v() {
int num = 220;
System.out.println("原始电压为" + num + "伏特");
return num;
}
}
/**
* 目标接口
*/
public interface Target {
public int outPut5v();
}
/**
* 类适配器
*/
public class ClassAdapter implements Target {
/**
* 将Adaptee聚合到当前类中,而不再是通过继承方式
*/
private Adaptee adaptee;
public ClassAdapter(Adaptee adaptee) {
this.adaptee = adaptee;
}
@Override
public int outPut5v() {
//获取220V电压
int outPut220v = adaptee.outPut220v();
//转换成目标接口所需要的
return outPut220v / 44;
}
}
/**
* 客户端调用类
*/
public class Test {
public static void main(String[] args) {
System.out.println("对象适配器模式");
//被适配类的对象
Adaptee adaptee = new Adaptee();
Target target = new ClassAdapter(adaptee);
System.out.println("手机能接受电压为" + target.outPut5v() + "伏特");
}
}
1、优缺点说明:
-
把多个不同的被适配者适配到同一个目标,也就是说,同一个适配器可以把被适配者类和他的子类都适配到目标接口。
-
与类适配器模式相比,要想重写被适配者类的方法就不容易。
5、接口适配器模式实现
1、接口适配器模式称为适配器模式(Default Adapter Pattern)或缺省适配器模式。
2、当不需要全部实现接口提供的方法时,可先设计一个抽象类实现接口,并为该接口中每个方法提供一个默认实现(空方法),那么该抽象类的子类可有选择地覆盖父类的某些方法来实现需求。
/**
* 被适配的类
*/
public class Adaptee {
public int outPut220v() {
int num = 220;
System.out.println("原始电压为" + num + "伏特");
return num;
}
}
/**
* 接口可有更多的抽象方法,而不仅仅局限于一种,比作万能的适配类
* 输出220v、110v、20v、5v电压
*/
public interface OutputAdapter {
public int outPut220V();
public int outPut110V();
public int outPut20V();
public int outPut5V();
}
/**
* 中间适配器,用于实现默认的接口方法,等着子类去实现需要的方法。
*/
public abstract class AbstractAdapter implements OutputAdapter {
protected Adaptee adaptee;
public AbstractAdapter(Adaptee adaptee) {
this.adaptee = adaptee;
}
@Override
public int outPut220V() {
return 0;
}
@Override
public int outPut110V() {
return 0;
}
@Override
public int outPut20V() {
return 0;
}
@Override
public int outPut5V() {
return 0;
}
}
/**
* 5V的具体实现
*/
public class Adapter5V extends AbstractAdapter {
public Adapter5V(Adaptee adaptee) {
super(adaptee);
}
@Override
public int outPut5V() {
int outPut = 0;
if (adaptee != null) {
outPut = adaptee.outPut220v() / 44;
}
return outPut;
}
}
/**
* 客户端调用类
*/
public class Test {
public static void main(String[] args) {
//已经有具体实现类的调用方式
Adapter5V adapter5V = new Adapter5V(new Adaptee());
System.out.println("已经有具体实现类的调用方式,手机能接受电压为" + adapter5V.outPut5V() + "伏特");
//没有具体的实现类的调用方式
AbstractAdapter abstractAdapter = new AbstractAdapter(new Adaptee()) {
@Override
public int outPut110V() {
int outPut = 0;
if (adaptee != null) {
outPut = adaptee.outPut220v() / 2;
}
return outPut;
}
};
System.out.println("没有具体的实现类的调用方式,笔记本能接受电压为" + abstractAdapter.outPut110V() + "伏特");
}
}
/**
* 运行结果:
* 原始电压为220伏特
* 已经有具体实现类的调用方式,手机能接受电压为5伏特
* 原始电压为220伏特
* 没有具体的实现类的调用方式,笔记本能接受电压为110伏特
*/
6、优缺点说明
1、优点:
-
将目标类和被适配者类解耦
-
增加了类的透明性和复用性,将具体的实现封装在适配者类中,对于客户端类来说是透明的,而且提高了适配者的复用性
-
灵活性和扩展性都非常好,符合开闭原则。
2、缺点:
-
适配器编写过程需要结合业务场景全面考虑,可能会增加系统的复杂性。
-
增加代码阅读难度,降低代码可读性,过多使用适配器会使系统代码变得凌乱。
四、桥接模式
1、概述
1、定义:
桥接(Bridge)模式是将抽象与实现分离,使它们可以独立变化,它是用组合关系代替继承关系来实现,从而降低了抽象和实现这两个可变维度的耦合度。
2、它是一种结构型设计模式,Bridge模式基于类的最小设计原则
,通过使用封装、聚合及继承等行为让不同的类承担不同的职责。
3、它的主要特点是把抽象(Abstraction)与行为实现 (Implementation)分离开来,从而可以保持各部分的独立性以及应对他们的功能扩展。
2、主要角色
1、抽象类(Abstraction):定义抽象类,并包含一个实现类接口类型的对象引用。
2、扩充抽象类(Refined Abstraction):在系统中可能不止一个,实现抽象类定义的业务方法,是抽象类的子类,通过组合关系调用实现类接口中的业务方法。
3、实现类接口(Implementor):定义实现类接口,供扩充抽象类调用。
4、具体实现类(ConcreteImplementor):在系统中可能不止一个,给出实现类接口的具体实现。
3、桥接模式实现
/**
* 实现类接口(手机品牌类)
*/
public interface BrandImplementor {
public void open();
public void close();
public void call();
}
/**
* 具体实现类(小米手机)
*/
public class Xiaomi implements BrandImplementor {
@Override
public void open() {
System.out.println("小米手机开机~");
}
@Override
public void close() {
System.out.println("小米手机关机~");
}
@Override
public void call() {
System.out.println("小米手机打电话~");
}
}
/**
* 具体实现类(Vivo手机)
*/
public class Vivo implements BrandImplementor {
@Override
public void open() {
System.out.println("Vivo手机开机~");
}
@Override
public void close() {
System.out.println("Vivo手机关机~");
}
@Override
public void call() {
System.out.println("Vivo手机打电话~");
}
}
/**
* 抽象类:手机抽象类
*/
public abstract class PhoneAbstraction {
//组合品牌
private BrandImplementor brandImplementor;
/**
* 构造方法
* @param brandImplementor
*/
public PhoneAbstraction(BrandImplementor brandImplementor) {
this.brandImplementor = brandImplementor;
}
public void open() {
brandImplementor.open();
}
public void close() {
brandImplementor.close();
}
public void call() {
brandImplementor.call();
}
}
/**
* 扩充抽象类A,实现PhoneAbstraction中的方法
*/
public class RefinedAbstractionA extends PhoneAbstraction {
/**
* 构造方法
* @param brandImplementor
*/
public RefinedAbstractionA(BrandImplementor brandImplementor) {
super(brandImplementor);
}
@Override
public void open() {
System.out.println("6 + 128G内存");
super.open();
}
@Override
public void close() {
System.out.println("6 + 128G内存");
super.close();
}
@Override
public void call() {
System.out.println("6 + 128G内存");
super.call();
}
}
/**
* 扩充抽象类B,实现PhoneAbstraction中的方法
*/
public class RefinedAbstractionB extends PhoneAbstraction {
/**
* 构造方法
* @param brandImplementor
*/
public RefinedAbstractionB(BrandImplementor brandImplementor) {
super(brandImplementor);
}
@Override
public void open() {
System.out.println("8 + 256G内存");
super.open();
}
@Override
public void close() {
System.out.println("8 + 256G内存");
super.close();
}
@Override
public void call() {
System.out.println("8 + 256G内存");
super.call();
}
}
/**
* 客户端调用类
*/
public class Test {
public static void main(String[] args) {
RefinedAbstractionA a = new RefinedAbstractionA(new Xiaomi());
a.open();
a.call();
a.close();
System.out.println("=========================================");
RefinedAbstractionB b = new RefinedAbstractionB(new Vivo());
b.open();
b.call();
b.close();
}
}
/**
* 运行结果:
* 6 + 128G内存
* 小米手机开机~
* 6 + 128G内存
* 小米手机打电话~
* 6 + 128G内存
* 小米手机关机~
* =========================================
* 8 + 256G内存
* Vivo手机开机~
* 8 + 256G内存
* Vivo手机打电话~
* 8 + 256G内存
* Vivo手机关机~
*/
4、优缺点说明
1、优点:
-
抽象与实现分离,扩展能力强,符合开闭原则,符合合成复用原则。
-
对于系统的高层部分,只需要知道抽象部分和实现部分的接口就可以了,其它的部分由具体业务来完成。
-
桥接模式替代多层继承方案,可以减少子类的个数,降低系统的管理和维护成本。
2、缺点:
-
由于聚合关系建立在抽象层,要求开发者针对抽象化进行设计与编程,能正确地识别出系统中两个独立变化的维度,这增加了系统的理解与设计难度。
5、适用场景
1、需要在抽象类和具体类之间增加更多灵活性。
2、类中存在多个独立变化的维度,且这些维度都需要独立进行扩展。
3、不希望使用多层继承导致系统类的个数急剧增加。