👈️上一篇:享元模式
回 顾:结构型设计模式
1.代理模式👈️
2.装饰器模式👈️
3.适配器模式👈️
4.组合模式👈️
5.桥接模式👈️
6.外观模式👈️
7.享元模式👈️
设计模式-专栏👈️
文章目录
- 结构型模式对比
- 概览
- 代理模式
- 明星接口IStar:上层抽象主题
- 明星类Star:主题类,实现上层抽象
- 经纪人代理人Proxy
- 测试
- 装饰模式
- 明星接口IStar:上层抽象构件
- 明星类Star的代码
- 替身演员Standin(被装饰类角色)
- 抽象装饰类Decorator
- 具体装饰类ConcreteDecorator
- 测试类:演员演戏,以及被装饰的替身演戏
- 适配器模式
- 明星接口IStar:目标(Target)角色
- 适配器的代码Adapter:将替身演员(源角色) 适配到 明星接口(目标接口)
- 替身演员Standin:源(Adaptee)角色
- 演员接口IActor:替身演员(源角色)上层抽象接口
- 测试类:明星自己演戏 && 适配的替身演员演戏
- 参考
结构型模式对比
结构类模式包括:代理模式、装饰模式、适配器(变压器)模式、组合模式、桥梁模式、门面(外观)模式、享元模式,它们都是通过组合类或对象产生更复杂的结构以适应更高层次的逻辑需求
其中:
-
组合模式、桥梁模式、外观模式、享元模式有各自显著特点,易区分
-
组合模式(Composite Pattern)注重形成上下层次间的“树形结构”。
-
桥接模式(Bridge Pattern)主要注重的是解耦抽象与实现,使得它们可以独立地变化。
通过引入抽象层与实现层的概念,并利用组合关系来解耦抽象与实现。它使得抽象层与实现层可以独立地变化,提高了系统的灵活性和扩展性。在需要频繁地修改或扩展系统时,桥梁模式是一种非常有效的设计模式。
-
外观模式(Facade Pattern)提供了一种统一的接口,用于简化对复杂子系统的访问,隐藏子系统的细节,使得客户端只需与外观对象交互,而无需与子系统中的多个对象交互。
-
享元模式(Flyweight Pattern)是池技术实现的重要方式,系统内有此对象就返回该对象的引用,否则创建该对象
-
-
主要对代理模式(Proxy Pattern)、装饰模式(Decorator Pattern)和适配器模式(Adapter Pattern)进行对比,这三个模式有一个共同点,它们都能够对类进行“包装”(wrapping ),但它们之间的主要区别如下
- 装饰模式是代理模式的一个特殊应用,虽然它们都具有相同的接口,但装饰模式是对类的功能进行加强或减弱,重点是类的功能变化;而代理模式着重代理过程的控制。
- 装饰模式和适配器模式都能对类进行“包装”,但装饰模式包装的是同一家族(相同接口或父类)的对象,而适配器模式可以修饰不同接口的对象,主要是将非本家族的对象伪装成同一家族对象。
- [记]:
- 【代理模式】中,客户端需要创建被代理对象(主题类),创建代理类并注入主题类,从而持有被代理对象,进行附加业务逻辑处理;
- 代理类通过组合方式组合上层抽象接口到类中,构造函数实际上用于注入主题类,从而使得代理类持有主题类;
- 【装饰模式】装饰“本家”,【适配器模式】将不是“本家”的类伪装成“本家”的,达到适配效果。
- 具体装饰类构造注入被装饰类,调用抽象装饰父类构造器,传给抽象父类被装饰类。从而,使得抽象装饰父类持有被装饰对象;
- 【适配逻辑】:定义适配器类继承源(Adaptee)角色(Standin类)实现目标(Target)接口(IStar接口);从而使得适配器类中将源角色中的方法“移花接木”到实现的目标接口的方法中(用得到super调用源角色方法)
概览
- 代理模式
- 通过经纪人安排明星是否接拍戏、拍广告代言的示例来说明
- 装饰模式
- 通过替身演员被装饰“看上去就像演员本身”去演戏来说明
- 适配器模式
- 通过对替身演员类进行适配到明星接口
代理模式
现在很多明星都有经纪人,所有的业务都是通过经纪人进行联络和活动,这是典型的代理模式。
下述内容用于实现任务描述:使用代理模式演示经纪人对明星的代理活动
经纪人代理明星,安排是否拍戏,是否广告代言,类图如下:
明星接口IStar:上层抽象主题
public interface IStar {
// 明星演戏
public abstract void action();
// 明星广告代言
public abstract void adver();
}
明星类Star:主题类,实现上层抽象
public class Star implements IStar {
// 姓名
private String name;
// 构造函数
public Star(String name) {
this.name = name;
}
@Override
public void action() {
System.out.println(this.name + "在演戏中");
}
@Override
public void adver() {
System.out.println(this.name + "在做广告代言");
}
}
经纪人代理人Proxy
代理角色类,实现上层抽象,同时将上层抽象(实际注入主题类即被代理类)组合(是一种强聚合关系,代表部分与整体关系)到本类中
public class Proxy implements IStar {
private IStar star;
// 构造注入上层抽象类型的对象
public Proxy(IStar star) {
this.star = star;
}
// 代理明星演戏
@Override
public void action() {
Random random = new Random();
if (random.nextBoolean()) {
System.out.println("经纪人同意安排明星演戏");
this.star.action();
} else {
System.out.println("明星档期已满,不能安排演戏");
}
}
@Override
public void adver() {
Random random = new Random();
if (random.nextBoolean()) {
System.out.println("经纪人同意安排明星广告代言");
this.star.adver();
} else {
System.out.println("明星档期已满,不能安排广告代言");
}
}
}
测试
经纪人代理明星,安排是否拍戏,是否广告代言
public class StarProxyTest {
public static void main(String[] args) {
// 定义一个明星
IStar star = new Star("范冰冰");
// 定义一个经纪人
Proxy proxy = new Proxy(star);
// 代理安排演戏否
proxy.action();
// 代理安排广告代言否
proxy.adver();
}
}
------
经纪人同意安排明星演戏
范冰冰在演戏中
明星档期已满,不能安排广告代言
装饰模式
现在很多明星在演戏时都使用替身,其实就是将替身进行修饰,使观众以为是明星自己演戏。
下述内容用于实现任务描述:使用装饰模式将替身演员修饰成明星.
替身演员被装饰达到去替代演员演戏的效果,类图如下:
明星接口IStar:上层抽象构件
将主题类方法进行抽象,用于被装饰类也实现此接口,从而被具体装饰类所装饰
public interface IStar {
// 明星演戏
public abstract void action(String context);
}
明星类Star的代码
public class Star implements IStar {
@Override
public void action(String context) {
System.out.println("------------");
System.out.println("明星亲自演戏" + context);
System.out.println("------------");
}
}
替身演员Standin(被装饰类角色)
public class Standin implements IStar {
@Override
public void action(String context) {
System.out.println("替身演戏" + context);
}
}
抽象装饰类Decorator
public abstract class Decorator implements IStar {
private IStar star;
protected Decorator(IStar star) {
this.star = star;
}
@Override
public void action(String context) {
this.star.action(context);
}
}
具体装饰类ConcreteDecorator
public class ConcreteDecorator extends Decorator {
// 构造注入被装饰类,调用抽象装饰父类构造器,传给抽象父类被装饰类。
// 从而,使得抽象装饰父类持有被装饰对象
public ConcreteDecorator(IStar star) {
super(star);
}
@Override
public void action(String context) {
System.out.println("------------");
//添加具体修饰逻辑
System.out.println("进行化妆、造型,让人看上去像明星");
super.action(context);
System.out.println("------------");
}
}
测试类:演员演戏,以及被装饰的替身演戏
public class DecoratorTest {
public static void main(String[] args) {
// 明星自己演戏
IStar star = new Star();
star.action("表演10分钟");
//在找替身演员替演
IStar standin = new Standin();
standin = new ConcreteDecorator(standin);
standin.action("表演5分钟");
}
}
------------
明星亲自演戏表演10分钟
------------
------------
进行化妆、造型,让人看上去像明星
替身演戏表演5分钟
------------
[注意]:Star和Standin都继承IStar接口,Decorator装饰类是对同一家族的类进行修饰。
适配器模式
下述内容用于实现任务描述:使用适配器模式演示替身演员和明星
此示例适配器角色用于把替身演员类适配到明星上层抽象接口。类图如下:
适配逻辑:定义适配器类继承源(Adaptee)角色(Standin类)实现目标(Target)接口(IStar接口);从而使得适配器类中将源角色中的方法“移花接木”到实现的目标接口的方法中(用得到super调用源角色方法)
明星接口IStar:目标(Target)角色
public interface IStar {
// 明星演戏
public abstract void action(String context);
}
明星类Star的代码
public class Star implements IStar {
@Override
public void action(String context) {
System.out.println("明星亲自演戏" + context);
}
}
适配器的代码Adapter:将替身演员(源角色) 适配到 明星接口(目标接口)
public class Adapter extends Standin implements IStar {
@Override
public void action(String context) {
// 让替身演员演戏
super.play(context);
}
}
替身演员Standin:源(Adaptee)角色
public class Standin implements IActor {
@Override
public void play(String context) {
// 替身演员演戏
System.out.println("替身演戏" + context);
}
}
演员接口IActor:替身演员(源角色)上层抽象接口
public interface IActor {
// 演员演戏
public abstract void play(String context);
}
测试类:明星自己演戏 && 适配的替身演员演戏
public class TestAdapter {
public static void main(String[] args) {
IStar star = new Star();
star.action("表演10分钟");
// 再找替身演员替演
star = new Adapter();
star.action("表演5分钟");
}
}
------
明星亲自演戏表演10分钟
替身演戏表演5分钟
[注意] Star和Standin分别继承不同的接口,Adapter适配器可以对不同类型的类进行包装。
参考
《设计模式(Java版)韩敬海主编》
👈️上一篇:享元模式
回 顾:结构型设计模式
1.代理模式👈️
2.装饰器模式👈️
3.适配器模式👈️
4.组合模式👈️
5.桥接模式👈️
6.外观模式👈️
7.享元模式👈️
设计模式-专栏👈️