结构型模式:代理/适配器/装饰/享元/桥接/组合/门面
代理模式
为其他对象提供一种代理以控制对这个对象的访问
使用场景
当不想直接访问某个对象或访问存在困难时,可以通过一个代理对象来间接访问,
为了保证客户端使用的透明性,委托对向与代理对象需要实现相同的接口
1 2 3 4 5 6 7 8 9 10 11
| interface ProxyInterface { void test(); } class A implements ProxyInterface { @Override public void test() { System.out.println("被代理类"); } }
|
静态代理
代理者的代码由程序员自己或通过一些自动化工具生成的固定代码,再对其进行编译,
即我们的代码在运行前代理类的class编译文件就已经存在
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| class MyProxy implements ProxyInterface { private ProxyInterface m; public MyProxy(ProxyInterface m) { this.m = m; } @Override public void test() { System.out.println("静态代理=>前执行"); m.test(); System.out.println("静态代理=>后执行"); } } A a = new A(); new MyProxy(a).test();
|
动态代理
通过反射机制动态的生成代理者的对象,常用的有jdk动态代理、cglib动态代理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| class DynamicProxy implements InvocationHandler { private Object obj; public DynamicProxy(Object obj) { this.obj = obj; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("动态代理=>前执行"); Object result = method.invoke(obj, args); System.out.println("动态代理=>后执行"); return result; } }
|
main方法调用
1 2 3 4 5 6 7 8
| A a = new A(); InvocationHandler invocationHandler = new DynamicProxy(a); ProxyInterface mProxy = (ProxyInterface) Proxy.newProxyInstance( a.getClass().getClassLoader(), a.getClass().getInterfaces(), invocationHandler); mProxy.test();
|
适配器模式
把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的二个类能够在一起工作
使用场景
接口不兼容、建立一个可重复使用的类用于类与类之间的合作、需要一个统一的输出接口但输入类型不可预知
1 2 3 4 5 6 7 8 9 10
| interface FiveVolt { int getVolt5(); } class Volt200 { public int getVolt200(){ return 200; } }
|
类适配器模式
1 2 3 4 5 6 7
| class VoltAdapter extends Volt200 implements FiveVolt { @Override public int getVolt5() { return 5; } }
|
对象适配器模式
Adapter不是使用继承关系连接到Adaptee,而是使用组合关系
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| class VoltAdapter2 implements FiveVolt { private Volt200 mVolt200; public VoltAdapter2(Volt200 mVolt200) { this.mVolt200 = mVolt200; } public int getVolt200() { return mVolt200.getVolt200(); } @Override public int getVolt5() { return 5; } }
|
装饰模式
动态的给一个对象添加一些额外的职责,是继承关系的替代方式之一
使用场景
需要动态且透明的扩展类的功能时
抽象组件类
1 2 3
| abstract class Component { public abstract void operate(); }
|
具体实现类
1 2 3 4 5 6
| class ConcreteComponent extends Component { @Override public void operate() { System.out.println("被装饰的方法"); } }
|
抽象装饰类
1 2 3 4 5 6 7 8 9 10 11 12
| abstract class Decorator extends Component { private Component component; public Decorator(Component component) { this.component = component; } @Override public void operate() { component.operate(); } }
|
装饰者实现类
1 2 3 4 5 6 7 8 9 10 11 12
| class ConcreteDecorator extends Decorator { public ConcreteDecorator(Component component) { super(component); } @Override public void operate() { System.out.println("装饰方法=>前。。。"); super.operate(); System.out.println("装饰方法=>后。。。"); } }
|
具体main方法实现
1 2 3 4 5
| Component component = new ConcreteComponent(); Decorator decorator = new ConcreteDecorator(component); decorator.operate();
|
享元模式
用以尽可能减少内存使用量,使用共享对象可有效支持大量的细粒度对象
享元对象中的部分状态是可以共享,可共享的状态成为内部状态,不会随着环境的改变而改变,
不可共享状态称之为外部状态,会随环境的改变而改变
经典享元模式中会建立一个对象容器Map,键为享元对象的内部状态,值为享元对象本身,
客户端程序通过这个内部状态从享元工厂中获取享元对象,若有缓存则使用缓存对象,
否则创建一个享元对象并且放进容器中,这样就避免了创建过多对象的问题
使用场景
- 系统中存在大量的相似对象
- 细粒度的对象都具备较接近的外部状态,而且内部状态与环境无关
- 需要缓冲池的场景
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| class TicketFactroy { static Map<String,Ticket> map = new ConcurrentHashMap<>(); public static Ticket getTicket(String from ,String to) { String key = from + "-" + to; if(map.containsKey(key)) { return map.get(key); }else{ TrainTicket ticket = new TrainTicket(from, to); map.put(key, ticket); return ticket; } } }
|
桥接模式
将抽象部分与实现部分分离,使他们都可以进行独立地变化
使用场景
一个类存在二个独立变化的维度,且这二个维度都需要进行扩展
对于那些不希望使用继承或者因为多层次继承导致系统类的个数急剧增加的系统,也可以使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| interface Implementor { void operate(); } class ConcreteImplementor implements Implementor { @Override public void operate() { } } abstract class Abstraction { private Implementor implementor; public Abstraction(Implementor implementor) { this.implementor = implementor; } public void operation() { implementor.operate(); } } class RefinedAbstraction extends Abstraction { public RefinedAbstraction(Implementor implementor) { super(implementor); } public void refinedOperation() { } }
|
组合模式
将对象组合成树形结构以表示”整体-部分”的层次结构,使得对单个对象和组合对象的使用具有一致性
使用场景
表示对象的部分-整体层次结构时或从一个整体中能够独立出部分模块或功能的场景
抽象根节点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| abstract class Component { protected String name; public Component(String name) { this.name = name; } public abstract void doSomething(); * 添加子节点 * @param child */ public abstract void addChild(Component child); * 移除子节点 * @param child */ public abstract void removeChild(Component child); * 获取子节点 * @param child */ public abstract Component getChild(int index); }
|
具体枝干结点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| class Composite extends Component { * 存储结点的容器 */ private List<Component> list = new ArrayList<>(); public Composite(String name) { super(name); } @Override public void doSomething() { System.out.println(name); if(list != null) { for (Component c : list) { c.doSomething(); } } } @Override public void addChild(Component child) { list.add(child); } @Override public void removeChild(Component child) { list.remove(child); } @Override public Component getChild(int index) { return list.get(index); } }
|
叶子结点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| class Leaf extends Component { public Leaf(String name) { super(name); } @Override public void doSomething() { System.out.println(name); } @Override public void addChild(Component child) { throw new UnsupportedOperationException("叶子结点没有子节点"); } @Override public void removeChild(Component child) { throw new UnsupportedOperationException("叶子结点没有子节点"); } @Override public Component getChild(int index) { throw new UnsupportedOperationException("叶子结点没有子节点"); } }
|
具体main方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public static void main(String[] args) { Component root = new Composite("Root"); Component branch1 = new Composite("Branch1"); Component branch2 = new Composite("Branch2"); Component leaf1 = new Leaf("Leaf1"); Component leaf2 = new Leaf("Leaf2"); branch1.addChild(leaf1); branch2.addChild(leaf2); root.addChild(branch1); root.addChild(branch2); root.doSomething(); }
|
门面模式/外观模式
要求一个子系统外部与其内部的通信必须通过一个统一的对象进行,门面模式提供一个高层次的接口,使子系统更加易用
使用场景
为一个复杂子系统提供一个简单接口或当需构建一个层次结构的子系统时
具体代码参看:https://github.com/Lutils/DesignPattern