设计模式之结构型模式
一、结构型模式概述
结构型模式主要用于处理类与对象的组合。它描述了如何将类或对象结合在一起形成更大的结构,就像搭积木一样,通过不同的组合方式构建出复杂而强大的软件架构。其主要目的是简化系统的设计,提高系统的灵活性、可维护性和可扩展性。常见的结构型模式有代理模式、适配器模式、桥接模式、装饰器模式、外观模式、享元模式和组合模式。
二、代理模式
(一)定义与概念
代理模式是为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
(二)关键要点
- 控制访问:代理模式可以在访问目标对象之前进行权限检查、日志记录等操作,对目标对象的访问进行控制。
- 延迟加载:当目标对象创建开销较大时,可以通过代理模式实现延迟加载,只有在真正需要时才创建目标对象。
(三)代码示例
// 抽象主题接口
interface Subject {
void request();
}
// 真实主题类
class RealSubject implements Subject {
@Override
public void request() {
System.out.println("真实主题执行请求");
}
}
// 代理类
class Proxy implements Subject {
private RealSubject realSubject;
@Override
public void request() {
if (realSubject == null) {
realSubject = new RealSubject();
}
// 访问前的额外操作,如日志记录
System.out.println("代理记录访问日志");
realSubject.request();
}
}
在上述代码中,Proxy类代理了RealSubject类,在调用request方法时,先进行了日志记录操作,然后再调用真实主题的request方法。
三、适配器模式
(一)定义与概念
适配器模式将一个类的接口转换成客户希望的另外一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
(二)关键要点
- 接口转换:解决不兼容接口之间的适配问题,是一种补救模式。
- 类适配器和对象适配器:类适配器通过继承实现,对象适配器通过组合实现,在实际应用中可根据具体情况选择合适的方式。
(三)代码示例
// 目标接口
interface Target {
void request();
}
// 适配者类
class Adaptee {
public void specificRequest() {
System.out.println("适配者执行特定请求");
}
}
// 类适配器
class ClassAdapter extends Adaptee implements Target {
@Override
public void request() {
specificRequest();
}
}
// 对象适配器
class ObjectAdapter implements Target {
private Adaptee adaptee;
public ObjectAdapter(Adaptee adaptee) {
this.adaptee = adaptee;
}
@Override
public void request() {
adaptee.specificRequest();
}
}
在这个例子中,ClassAdapter通过继承Adaptee类实现了Target接口,ObjectAdapter则通过组合Adaptee对象实现了Target接口,两者都将Adaptee的specificRequest方法适配成了Target接口的request方法。
四、桥接模式
(一)定义与概念
桥接模式将抽象部分与它的实现部分分离,使它们都可以独立地变化。它是一种对象结构型模式,通过将抽象和实现解耦,使得两者可以沿着各自的维度进行扩展。
(二)关键要点
- 解耦抽象与实现:避免了抽象和实现的紧耦合,提高了系统的可维护性和可扩展性。
- 多维度变化:允许抽象和实现分别独立地进行变化,适用于系统中存在多个变化维度的情况。
(三)代码示例
// 抽象实现类接口
interface Implementor {
void operationImpl();
}
// 具体实现类A
class ConcreteImplementorA implements Implementor {
@Override
public void operationImpl() {
System.out.println("具体实现类A的操作");
}
}
// 具体实现类B
class ConcreteImplementorB implements Implementor {
@Override
public void operationImpl() {
System.out.println("具体实现类B的操作");
}
}
// 抽象类
abstract class Abstraction {
protected Implementor implementor;
public Abstraction(Implementor implementor) {
this.implementor = implementor;
}
public abstract void operation();
}
// 扩充抽象类
class RefinedAbstraction extends Abstraction {
public RefinedAbstraction(Implementor implementor) {
super(implementor);
}
@Override
public void operation() {
System.out.println("扩充抽象类开始操作");
implementor.operationImpl();
System.out.println("扩充抽象类操作结束");
}
}
在上述代码中,Abstraction类与Implementor接口通过构造函数进行关联,实现了抽象与实现的分离。RefinedAbstraction类可以根据不同的Implementor实现类进行不同的操作,体现了桥接模式的灵活性。
五、装饰器模式
(一)定义与概念
装饰器模式动态地给一个对象添加一些额外的职责。就增加功能来说,装饰器模式相比生成子类更为灵活。
(二)关键要点
- 动态添加功能:无需修改原有类的代码,通过装饰器类为对象动态添加功能。
- 多层装饰:可以对一个对象进行多层装饰,以实现复杂的功能组合。
(三)代码示例
// 抽象组件
abstract class Component {
public abstract void operation();
}
// 具体组件
class ConcreteComponent extends Component {
@Override
public void operation() {
System.out.println("具体组件的操作");
}
}
// 抽象装饰器
abstract class Decorator extends Component {
protected Component component;
public Decorator(Component component) {
this.component = component;
}
@Override
public void operation() {
component.operation();
}
}
// 具体装饰器A
class ConcreteDecoratorA extends Decorator {
public ConcreteDecoratorA(Component component) {
super(component);
}
@Override
public void operation() {
super.operation();
// 添加额外功能
System.out.println("具体装饰器A添加的功能");
}
}
// 具体装饰器B
class ConcreteDecoratorB extends Decorator {
public ConcreteDecoratorB(Component component) {
super(component);
}
@Override
public void operation() {
super.operation();
// 添加额外功能
System.out.println("具体装饰器B添加的功能");
}
}
在这个例子中,ConcreteDecoratorA和ConcreteDecoratorB可以为ConcreteComponent动态添加不同的功能,而且可以进行多层装饰,如先使用ConcreteDecoratorA装饰,再使用ConcreteDecoratorB装饰。
六、外观模式
(一)定义与概念
外观模式为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
(二)关键要点
- 简化接口:将复杂的子系统接口封装成一个简单的统一接口,降低客户端与子系统的耦合度。
- 解耦:客户端只需要与外观类交互,而不需要了解子系统内部的复杂结构和交互细节。
(三)代码示例
// 子系统类A
class SubsystemA {
public void operationA() {
System.out.println("子系统A的操作");
}
}
// 子系统类B
class SubsystemB {
public void operationB() {
System.out.println("子系统B的操作");
}
}
// 子系统类C
class SubsystemC {
public void operationC() {
System.out.println("子系统C的操作");
}
}
// 外观类
class Facade {
private SubsystemA subsystemA;
private SubsystemB subsystemB;
private SubsystemC subsystemC;
public Facade() {
subsystemA = new SubsystemA();
subsystemB = new SubsystemB();
subsystemC = new SubsystemC();
}
public void operation() {
subsystemA.operationA();
subsystemB.operationB();
subsystemC.operationC();
}
}
在上述代码中,Facade类封装了SubsystemA、SubsystemB和SubsystemC的操作,客户端只需要调用Facade的operation方法,就可以执行一系列子系统的操作,而无需了解子系统内部的具体实现。
七、享元模式
(一)定义与概念
享元模式运用共享技术有效地支持大量细粒度的对象。通过共享已经存在的对象来大幅度减少需要创建的对象数量,避免大量相似类的开销。
(二)关键要点
- 对象共享:通过共享对象来减少内存占用和提高性能,适用于大量重复对象的场景。
- 内部状态和外部状态:将对象的状态分为内部状态(不随环境改变而改变的可共享部分)和外部状态(随环境改变而改变的不可共享部分),在共享对象时,只共享内部状态。
(三)代码示例
// 抽象享元类
abstract class Flyweight {
protected String intrinsicState;
public Flyweight(String intrinsicState) {
this.intrinsicState = intrinsicState;
}
public abstract void operation(String extrinsicState);
}
// 具体享元类
class ConcreteFlyweight extends Flyweight {
public ConcreteFlyweight(String intrinsicState) {
super(intrinsicState);
}
@Override
public void operation(String extrinsicState) {
System.out.println("具体享元对象的内部状态:" + intrinsicState + ",外部状态:" + extrinsicState);
}
}
// 享元工厂类
class FlyweightFactory {
private Map<String, Flyweight> flyweights = new HashMap<>();
public Flyweight getFlyweight(String intrinsicState) {
if (!flyweights.containsKey(intrinsicState)) {
flyweights.put(intrinsicState, new ConcreteFlyweight(intrinsicState));
}
return flyweights.get(intrinsicState);
}
}
在这个例子中,FlyweightFactory类负责创建和管理享元对象,通过共享ConcreteFlyweight对象,减少了对象的创建数量。
八、组合模式
(一)定义与概念
组合模式将对象组合成树形结构以表示 “部分 - 整体” 的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
(二)关键要点
- 树形结构:用于表示对象的层次结构,方便对整个树或部分树进行操作。
- 统一操作:客户端可以统一地使用组合对象和单个对象,无需区分它们。
(三)代码示例
// 抽象组件
abstract class Component {
protected String name;
public Component(String name) {
this.name = name;
}
public abstract void add(Component component);
public abstract void remove(Component component);
public abstract void display(int depth);
}
// 叶子节点
class Leaf extends Component {
public Leaf(String name) {
super(name);
}
@Override
public void add(Component component) {
System.out.println("叶子节点不能添加子节点");
}
@Override
public void remove(Component component) {
System.out.println("叶子节点不能移除子节点");
}
@Override
public void display(int depth) {
for (int i = 0; i < depth; i++) {
System.out.print("-");
}
System.out.println("Leaf: " + name);
}
}
// 组合节点
class Composite extends Component {
private List<Component> children = new ArrayList<>();
public Composite(String name) {
super(name);
}
@Override
public void add(Component component) {
children.add(component);
}
@Override
public void remove(Component component) {
children.remove(component);
}
@Override
public void display(int depth) {
for (int i = 0; i < depth; i++) {
System.out.print("-");
}
System.out.println("Composite: " + name);
for (Component component : children) {
component.display(depth + 2);
}
}
}
在上述代码中,Composite类可以包含多个Component对象(包括Leaf和Composite),形成树形结构。客户端可以统一地对Leaf和Composite进行操作,如添加、移除和显示等。