【设计模式】常用的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)
将对象组合成树形结构以表示部分-整体的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
如,菜单-子菜单关系,文件夹-子文件夹关系等
应用实例:
- 部门组织架构
- 菜单-子菜单关系
- 文件夹-子文件夹关系
(完)