【设计模式】常用的23种设计模式(二)

简介
常用的设计模式分三大类:
创建型模式(Creational Patterns)
结构型模式(Structural Patterns)
行为型模式(Behavioral Patterns)

本章主要来介绍下常用的7种结构型设计模式。

结构型模式(Structural Patterns)
结构型模式主要关注类和对象的组合。继承的概念被用来组合接口和定义组合对象获取新功能的方式。

共7种:

  • 代理模式(Proxy Pattern)
  • 桥接模式(Bridge Pattern)
  • 装饰器模式(Decorator Pattern)
  • 适配器模式(Adapter Pattern)
  • 外观模式(Facade Pattern)
  • 享元模式(Flyweight Pattern)
  • 组合模式(Composite Pattern)

1、代理模式(Proxy Pattern)
代理模式就是多出一个代理类出来,替原对象进行一些操作。比如中介、律师等都是代理。

代理模式的应用场景:
如果已有的方法在使用的时候需要对原有的方法进行改进,此时有两种办法:
(1)修改原有方法来适应,这样违反了“对扩展开放,对修改关闭”的开闭原则。
(2)采用一个代理类调用原有的方法,且对产生的结果进行控制,这种方法就是代理模式。

举例说明:

代理模式类图代理模式类图

接口及实现类:

public interface Sourceable {
    public void method();
}

public class Source implements Sourceable {
    @Override
    public void method() {
        System.out.println("Source method1...");
    }
}

代理类:

public class Proxy implements Sourceable {
    private Source source;
    public Proxy() {
        super();
        this.source = new Source();
    }
    @Override
    public void method() {
        before();
        this.source.method();
        after();
    }
    public void before() {
        System.out.println("before Proxy...");
    }
    public void after() {
        System.out.println("after Proxy...");
    }
}

测试类:

public class ProxyTest {
    @Test
    public void test() {
        Proxy proxy = new Proxy();
        proxy.method();
    }
}

输出:

before Proxy...
Source method1...
after Proxy...

2、桥接模式(Bridge Pattern)
将抽象和实现解耦,使得二者可以独立变化。
像我们常用JDBC的DriverManager一样,JDBC切换数据库的时候,基本不需要改动代码,只需要修改驱动类和数据库连接即可。

示例:

桥接模式类图桥接模式类图

接口及实现类:

public interface Sourceable {
    public void method();
}

public class SubSource1 implements Sourceable {
    @Override
    public void method() {
        System.out.println("SubSource1 method1...");
    }
}

public class SubSource2 implements Sourceable {
    @Override
    public void method() {
        System.out.println("SubSource2 method1...");
    }
}

桥接抽象类及子类:

public abstract class Bridge {
    private Sourceable source;
    public void method1() {
        this.source.method();
    }
    public Sourceable getSource() {
        return source;
    }
    public void setSource(Sourceable source) {
        this.source = source;
    }
}

public class MyBridge extends Bridge {
    @Override
    public void method1() {
        getSource().method();
    }
}

测试类:

public class BridgeTest {
    @Test
    public void test() {
        Bridge bridge = new MyBridge();
        bridge.setSource(new SubSource1());
        bridge.method1();

        bridge.setSource(new SubSource2());
        bridge.method1();
    }
}

输出:

SubSource1 method1...
SubSource2 method1...

3、装饰器模式(Decorator Pattern)
给一个对象动态增加一些新的功能,要求装饰对象和被装饰对象实现同一个接口,装饰对象持有被装饰对象的实例
继承不能做到这一点,继承的功能是静态的,不能动态增删。

示例:

装饰器模式类图装饰器模式类图

接口及实现类:

public interface Sourceable {
    public void method();
}

public class Source implements Sourceable {
    @Override
    public void method() {
        System.out.println("Source method...");
    }
}

装饰器类:

public class Decorator implements Sourceable {
    private Sourceable source;
    public Decorator(Sourceable source) {
        super();
        this.source = source;
    }
    @Override
    public void method() {
        System.out.println("Decorator before...");
        source.method();
        System.out.println("Decorator after...");
    }
}

测试类:

public class DecoratorTest {
    @Test
    public void test() {
        Sourceable source = new Source();
        Decorator decorator = new Decorator(source);
        decorator.method();
    }
}

输出:

Decorator before...
Source method...
Decorator after...

4、适配器模式(Adapter Pattern)
将某个类的接口转换成客户期望的另一个接口表示,目的是消除接口不匹配造成的类的兼容性问题。

适配器模式主要分三类:

  • 类的适配器模式
  • 对象的适配器模式
  • 接口的适配器模式

类的适配器模式:当希望将一个类转换成满足另一个新接口的类时,可以使用一个新类,继承原有的类,实现新的接口即可;

对象的适配器模式:当希望将一个对象转换成满足另一个接口的对象时,可以创建一个Wrapper类,持有原类的一个实例,在Wrapper类的方法中,调用实例的方法即可;

接口的适配器模式:当不希望实现一个接口中的所有的方法时,可以创建一个抽象类Wrapper,实现所有方法,我们再写实现类的时候,继承抽象类,只实现需要的接口即可;

类的适配器模式-示例:

类的适配器模式类图类的适配器模式类图

将类Source转换成满足Targetable接口的类:
定义Adapter类,继承Source类,并实现Targetable接口即可。

接口及实现类:

public class Source {
    public void method1() {
        System.out.println("Source method1 ...");
    }
}

public interface Targetable {
    public void method1();
    public void method2();
}

public class Adapter extends Source implements Targetable {
    @Override
    public void method2() {
        System.out.println("Adapter method2 ...");
    }
}

测试类:

public class AdapterTest {
    @Test
    public void test() {
        Adapter adapter = new Adapter();
        adapter.method1();
        adapter.method2();
    }
}

输出:

Source method1 ...
Adapter method2 ...

对象的适配器模式-示例:

对象的适配器模式类图对象的适配器模式类图

接口及实现类:

public class Source {
    public void method1() {
        System.out.println("Source method1 ...");
    }
}

public interface Targetable {
    public void method1();
    public void method2();
}

public class Wrapper implements Targetable {
    private Source source;
    public Wrapper(Source source) {
        super();
        this.source = source;
    }
    @Override
    public void method1() {
        source.method1();
    }
    @Override
    public void method2() {
        System.out.println("Wrapper method2...");
    }
}

测试类:

public class AdapterTest {
    @Test
    public void test() {
        Source source = new Source();
        Wrapper wrapper = new Wrapper(source);
        wrapper.method1();
        wrapper.method2();
    }
}

输出:

Source method1 ...
Wrapper method2...

接口的适配器模式-示例:

接口的适配器模式类图接口的适配器模式类图

接口及实现类:

public interface Sourceable {
    public void method1();
    public void method2();
    public void method3();
}

public abstract class AbstractWrapper implements Sourceable {
    @Override
    public void method1() {
        System.out.println("AbstractWrapper method1...");
    }
    @Override
    public void method2() {
        System.out.println("AbstractWrapper method2...");
    }
    @Override
    public void method3() {
        System.out.println("AbstractWrapper method3...");
    }
}

public class SubSource extends AbstractWrapper {
    @Override
    public void method1() {
        System.out.println("SubSource method1...");
    }
}

测试类:
public class AdapterTest {

@Test
public void test() {
    SubSource subSource = new SubSource();
    subSource.method1();
    subSource.method2();
    subSource.method3();
}

}

输出:

SubSource method1...
AbstractWrapper method2...
AbstractWrapper method3...

5、外观模式(Facade Pattern)
通过外观类,隐藏系统的复杂度,降低客户端和系统之间的耦合度。

应用实例:

  • 医院接待员
  • Java MVC架构

示例:
基础类:

public class CPU {
    public void startup() {
        System.out.println("CPU startup...");
    }
    public void shutdown() {
        System.out.println("CPU shutdown...");
    }
}

public class Disk {
    public void startup() {
        System.out.println("Disk startup...");
    }
    public void shutdown() {
        System.out.println("Disk shutdown...");
    }
}

public class Memory {
    public void startup() {
        System.out.println("Memory startup...");
    }
    public void shutdown() {
        System.out.println("Memory shutdown...");
    }
}

外观类:

public class Computer {
    private CPU cpu;
    private Memory memory;
    private Disk disk;

    public Computer() {
        this.cpu = new CPU();
        this.memory = new Memory();
        this.disk = new Disk();
    }
    public void startup() {
        System.out.println("Computer startup...");
        cpu.startup();
        memory.startup();
        disk.startup();
    }
    public void shutdown() {
        System.out.println("Computer shutdown...");
        cpu.shutdown();
        memory.shutdown();
        disk.shutdown();
    }
}

测试类:

public class FacadeTest {
    @Test
    public void test() {
        Computer computer = new Computer();
        computer.startup();
        computer.shutdown();
    }
}

输出:

Computer startup...
CPU startup...
Memory startup...
Disk startup...
Computer shutdown...
CPU shutdown...
Memory shutdown...
Disk shutdown...

6、享元模式(Flyweight Pattern)
享元模式的主要目的是实现对象的共享,当系统中对象多的时候,可以减少内存的开销,通常与工厂模式一起使用。
FlyWeightFactory负责创建和管理享元单元,当一个客户端请求时,工厂需要检查当前对象池中是否有符合条件的对象,如果有,就返回已存在的对象,如果没有,则创建一个新对象。
一提到共享池,我们很容易联想到java里面JDBC的连接池,通过连接池的管理,实现了数据库连接的共享,不需要每次都创建连接,提升系统的性能。

应用实例:

  • Java中的String,如果有则返回,如果没有则创建字符串并保存在字符串缓冲池中。
  • 数据库的连接池

7、组合模式(Composite Pattern)
将对象组合成树形结构以表示部分-整体的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
如,菜单-子菜单关系,文件夹-子文件夹关系等

应用实例:

  • 部门组织架构
  • 菜单-子菜单关系
  • 文件夹-子文件夹关系

(完)

添加新评论