结构型设计模式

291 阅读6分钟

前言

前面介绍过设计模式原则和设计模式分类,结构型设计模式包括适配器模式,装饰模式,代理模式,外观模式,桥接模式,组合模式和享元模式。
为什么叫结构模式?
因为他们都是通过组合类或者对象产生更大的结构以适应高层次的逻辑需求。

image.png

1. 适配器模式

1.1 定义

适配器模式(Adapter Pattern) Convert the interface of a class into another interface clients expect.Adapter lets classes work together that couldn't otherwise because of incompatible interfaces.
将一个类的接口变成客户端期待的另外一个接口,从而使原来因为接口不匹配的的两个类一起工作。

image.png

伪代码

public class Client {

    public static void main(String[] args) {
        Target target = new ConcreteTarget();
        target.request();
        Target target1 = new Adapter();
        target1.request();
    }
}

// 目标角色
public interface Target {

    public void request();
}

// 目标角色实现类
public class ConcreteTarget implements Target{
    @Override
    public void request() {
        // 业务逻辑
    }
}

// 源角色
public class Adaptee {

    public void doSomething() {

    }
}

// 适配器角色
public class Adapter extends Adaptee implements Target{
    @Override
    public void request() {
        super.doSomething();
    }
}

使用场景

  • java.util.Arrays#asList()
  • javax.swing.JTable(TableModel)
  • java.io.InputStreamReader(InputStream)
  • java.io.OutputStreamWriter(OutputStream)
  • javax.xml.bind.annotation.adapters.XmlAdapter#marshal()
  • javax.xml.bind.annotation.adapters.XmlAdapter#unmarshal()

代码案例

2. 装饰模式

2.1 定义

装饰模式(Decorator Pattern)
Attach additional responsibilities to an object dynamically keeping the same interface. Decorators provide a flexible alternative to subclassing for extending functionality.
动态的给一个对象添加一些额外的职责,就增加功能来说,装饰模式相比生成子类更加灵活。

image.png 在类图种4个角色

  1. Compoent 抽象构建
  2. ConcreteCompoent 具体构件
  3. Decorator装饰角色
  4. 具体的装饰校色ConcreteDecoratorA 具体的装饰类

伪代码

public class Client {

    public static void main(String[] args) {
        Component component = new ConcreteComponent();
        // 第一次修饰
        component = new ConcreteDecorator1(component);
        
        // 第二次修饰
        component = new ConcreteDecorator2(component);
        // 运行
        component.operate();
    }
}


public abstract class Component {

    public abstract void operate();
}

public class ConcreteComponent extends Component{
    @Override
    public void operate() {
        System.out.println("do something");
    }
}


public abstract class Decorator extends Component {

    private Component component = null;

    public Decorator(Component component) {
        this.component = component;
    }

    @Override
    public void operate() {
        this.component.operate();
    }
}

public class ConcreteDecorator1 extends Decorator{

    public ConcreteDecorator1(Component component) {
        super(component);
    }

    // 定义自己的修饰方法
    public void method1() {

    }

    // 重写父类的方法
    @Override
    public void operate() {
        this.method1();
        super.operate();
    }
}

2.2 使用场景

为一个对象动态的加上一系列的动作,而不需要因为这些动作的不同而产生大量的继承类。 一些典型的应用场景: 一些典型的。

  • java.io.BufferedInputStream(InputStream)
  • java.io.DataInputStream(InputStream)
  • java.io.BufferedOutputStream(OutputStream)
  • java.util.zip.ZipOutputStream(OutputStream)
  • java.util.Collections#checked[List|Map|Set|SortedSet|SortedMap]

2.3 代码案例

经典的例子IO流为例

3. 代理模式

3.1 定义

代理模式(Proxy Pattern)是一个使用效率非常高的模式。 Provider a surrogate or placeholder for another object to control access to id。

3.2 使用场景

比如Spring AOP就是经典的代理模式

image.png

  • Subject 抽象主题角色,可以是抽象类或者接口
  • RealSubject 具体主题角色,也叫委托角色和代理角色
  • Proxy 代理主题角色,也叫委托类,代理类

伪代码

public class Proxy implements Subject{

    private Subject subject = null;
    public Proxy() {
        this.subject = new Proxy();
    }
    public Proxy(Object ... objects) {

    }
    @Override
    public void request() {
        this.before();
        this.subject.request();
        this.after();
    }

    private void before(){
    }
    private void after() {
    }
}


public interface Subject {

    public void request();
}


public class RealSubject implements Subject{
    @Override
    public void request() {
        // 业务逻辑处理
    }
}

我们看下Spring AOP动态代理图 image.png

3.3 代码案例

4. 外观模式

4.1 定义

门面模式(Facade Pattern)也叫外观模式,是一种比较常用的封装模式。 Provide a unified interface to a set of iterfaces in a subsystem. Facade defines a higher-level interface that makes the subsystem easier to use.

4.2 使用场景

  1. 为一个复杂的模块或子系统提供一个外界访问的接口,比如我们系统分层中接口api可以作为一个门面模式分层.

4.3 代码案例

5. 桥接模式

5.1 定义

桥接模式(bridge Pattern)
Decouple an abstraction from its implementation so that the two can vary independently。
将抽象和实现解耦,使得两者可以独立变化。

5.2 使用场景

把抽象和实现解藕,于是接口和实现可在完全独立开来。

image.png 桥接模式种的4种角色:

  • Abstraction 抽象化角色,他的主要职责是定义出该角色的行为,同时保存一个对实现化角色的引用,该角色一般是抽象类.
  • Implementor 实现化角色, 他是接口或者抽象类,定义角色必须的行为和属性.
  • RefinedAbstraction 修正抽象化角色,它引用实现化角色,对抽象化角色进行修正.
  • ConcreteImplement 具体实现化角色,它实现接口或抽象类中定义的方法和属性.

代码比较复杂,看下伪代码

public class Client {

    public static void main(String[] args) {
        // 定义一个实现化角色
        Implementor implementor = new ConcreteImplementor1();
        // 定义一个抽象化角色
        Abstraction abstraction = new RefinedAbstraction(implementor);
        // 执行逻辑
        abstraction.request();
    }
}

// 实现化角色
public interface Implementor {

    public void doSomething();

    public void doAnything();
}

// 抽象化角色
public abstract class Abstraction {
    // 定义对实现化角色的引用
    private Implementor implementor;
    // 约束子类必须实现该构造函数
    public Abstraction(Implementor implementor) {
        this.implementor = implementor;
    }
    //自身的行为或者属性
    public void request() {
        this.implementor.doSomething();
    }
    // 获得实现化角色
    public Implementor getImplementor() {
        return implementor;
    }
}

// 具体实现
public class ConcreteImplementor1 implements Implementor {
    @Override
    public void doSomething() {
        // 业务逻辑处理
    }

    @Override
    public void doAnything() {
        // 业务逻辑处理
    }
}
// 修正角色
public class RefinedAbstraction extends Abstraction {

    // 重写构造函数
    public RefinedAbstraction(Implementor implementor) {
        super(implementor);
    }

    // 修正父类的行为
    @Override
    public void request() {
        // 业务逻辑处理
        super.request();
        super.getImplementor().doAnything();
    }
}

5.3 代码案例

6. 组合模式

6.1 定义

组合模式(Composite Pattern) Compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly.
将对象组合成树型结构以表示“整体-部分”的层次结构,使得用户对单个对象和组合对象的使用具有一致性。

6.2 使用场景

维护一个整体和部分关系的场景,比如菜单,文件和文件夹管理等等.

image.png

  • Component 抽象构建角色,定义参加组合对象的共有方法和属性,可以定义一些默认的行为和属性.
  • Leaf 叶子构件角色,遍历的最小单位
  • Composite 树枝构件,组合树枝节点和叶子节点形成一个树形结构.

伪代码:

public class Client {
    public static void main(String[] args) {
        //创建根节点
        Composite root = new Composite();
        root.doSomething();
        // 树枝
        Composite branch = new Composite();
        // 叶子
        Leaf leaf = new Leaf();
        root.add(branch);
        branch.add(leaf);
    }

    // 递归
    public static void display(Composite root) {
        for (Component component : root.getChildren()) {
            if (component instanceof Leaf) {
                component.doSomething();
            } else {
                display((Composite) component);
            }
        }
    }
}

public abstract class Component {

    public void doSomething() {

    }
}

public class Composite extends Component {
    // 构件容器
    private ArrayList<Component> componentArrayList = new ArrayList<>();

    // 增加叶子构件
    public void add(Component component) {
        this.componentArrayList.add(component);
    }

    // 删除叶子构件
    public void remove(Component component) {
        this.componentArrayList.remove(component);
    }

    // 返回树
    public ArrayList<Component> getChildren() {
        return this.componentArrayList;
    }
}


public class Leaf extends Component {

    @Override
    public void doSomething() {

    }
}

6.3 代码案例

7. 享元模式

7.1 定义

享元模式(Flyweight Pattern)是池技术的重要实现方式.
Using sharing to support large numbers of fine-grained objects efficiently

7.2 使用场景

系统中存在大量的相似对象,有效率地存储大量的小的对象

image.png

  • Flyweight 抽象享元角色, 一个产品的抽象类,同时定义出对象的外部状态和内部状态的接口或者实现.
  • ConcreteFlyweight 具体享元角色,实现抽象角色定义的业务.
  • unsharedConcreteFlayweight 不能共享享元角色
  • FlyweightFactory 享元工厂, 构造对象池从池中获取对象.
public class FlyweightFactory {
    // 定义一个池容器
    private static HashMap<String, Flyweight> pool = new HashMap<>();

    // 享元工厂
    public static  Flyweight getFlyweight(String extrinsic) {
        Flyweight flyweight = null;
        if (pool.containsKey(extrinsic)) {
            flyweight = pool.get(extrinsic);
        } else {
            flyweight = new ConcreteFlyweightA(extrinsic);
            pool.put(extrinsic, flyweight);
        }
        return flyweight;
    }
}


public abstract class Flyweight {

    // 内部状态
    private String instrinsic;

    // 外部状态
    protected final String extrinsic;

    // 要求享元角色必须接收外部状态
    public Flyweight(String extrinsic) {
        this.extrinsic = extrinsic;
    }

    public abstract void operate();

    public String getInstrinsic() {
        return instrinsic;
    }

    public void setInstrinsic(String instrinsic) {
        this.instrinsic = instrinsic;
    }
}


public class ConcreteFlyweightA extends Flyweight {

    // 接收外部状态
    public ConcreteFlyweightA(String extrinsic) {
        super(extrinsic);
    }

    // 根据外部状态进行逻辑处理
    @Override
    public void operate() {
        // 业务逻辑
    }
}

7.3 代码案例