结构型模式
- 如何组合类和对象以获得更大的结构
适配器
将一个接口转换成另一个接口
classDiagram
class Target {
+ops()
}
class Adapter {
+ops()
}
class Adaptee {
+run()
}
class ConcreteTarget {
+ops()
}
Target <|-- Adapter: 实现
Adaptee <--* Adapter: 组合
Target <|-- ConcreteTarget
Client --> Target
- 双向适配器
interface Target{
void ops();
}
class Adaptee{
public void run() { }
}
class Adapter implements Target{
private Adaptee adaptee;
public Adapter(Adaptee adaptee) {
this.adaptee = adaptee;
}
@Override
public void ops() {
// do something
adaptee.run();
}
}
// 使用
Target target = new Adapter(new Adaptee());
target.ops();
分类:
- 类适配器
- 对象适配
- 接口适配方式
桥接
将抽象部分与实现部分分离,使它们都可以独立地变化
abstract class Window {
//...
abstract setMenu(Menu menu)
}
interface Menu{}
class LinuxWindow extends Window{...}
class MacWindow extends Window{...}
class PlainMenu implements Menu{...}
class RichMenu implements Menu{...}
组合
将对象组合成树形结构的部分-整体层次结构,使得客户使用单个对象或组合对象都有一致性
interface Route {
Route segement1, segement2;
} // 路线
class NationalHighway implements Route{} // 国道
class CountryRoad implements Route {} // 乡道
组合模式很重要的一点就是客户端使用所有节点的方式都相同,同时这些节点内部又以组合的方式组合其他节点。
装饰器
给一个对象添加额外的职责
classDiagram
class Component {
+ops()
}
class ConcreteComponent {
+ops()
}
class Decorator {
+ops()
}
class ConcreteDecorator {
+ops()
-component Compoment
}
Component <|-- Decorator
Decorator <|-- ConcreteDecorator
Component <|-- ConcreteComponent
装饰器与被装饰的对象都拥有同一个接口,所以说,装饰器对客户来说是透明的
abstract class InputStream{...}
class FileInputStream extends InpurStream{...}
外观
为系统中的一组接口提供一致的界面
classDiagram
class Facade {
+ops()
}
class SystemA {
+opsA()
}
class SystemB {
+opsB()
}
Facade <-- SystemA
Facade <-- SystemB
Client --> Facade
class Facade{
private SubSystem1 subSystem1;
private SubSystem2 subSystem2;
void ops(){
subSystem1.ops1();
subSystem2.ops2();
}
}
// 使用
Facade facade = new Facade();
facade.ops();
享元
共享系统中大量的细粒度对象
- 提高性能
classDiagram
Flyweight <|-- ConcreteFlyweight
Flyweight <|-- UnsharedConcreteFlyweight
FlyweightFactory *--> Flyweight
class FlyweightFactory {
+getFlyweight(type)
}
Client --> FlyweightFactory
Client --> ConcreteFlyweight
Client --> UnsharedConcreteFlyweight
- FlyweightFactory:主要是用来确保合理地共享Flyweight,当用户请求一个Flyweight时,FlyweightFactory 会返回一个已有或者创建享元对象
- UnsharedConcreteFlyweight:不需要共享的Flyweight子类。因为Flyweight 接口共享成为可能,但它并不强制共享
class MessageFactory{
Message getHeartBeatMeessage();
}
interface Message{...}
class HeartBeatMessage implements Message{...}
代理
为其他对象提供一个代理访问控制
- 又称为委托模式
classDiagram
class Subject {
+action()
}
class SubjectProxy {
-target: ConcreteSubject
+action()
}
Subject <|-- ConcreteSubject
SubjectProxy o--> ConcreteSubject
Client --> Subject
静态代理
- 结构简单,代码繁琐
interface Subject{
void run();
}
class Proxy implements Subject{
private Subject realObject = new RealSubject();
void run(){
//before
realObject.run();
//after
}
}
// 使用
Subject subject = new Proxy();
subject.run();
动态代理
- JDK动态代理
SubjectImpl impl = new SubjectImpl();
Subject proxy = (Subject) Proxy.newProxyInstance(impl.getClass().getClassLoader(),
impl.getClass().getInterfaces(), (proxy1, method, args1) -> {
System.out.println("pre invoke");
return method.invoke(impl, args1);
});
proxy.request();
如果多个接口重名,则调用接口方法以第一个接口为主
- cglib动态代理
Enhancer enhancer = new Enhancer();
Object target = new Object();
enhancer.setSuperclass(Object.class);
enhancer.setCallback((MethodInterceptor) (obj, method, args1, proxy) -> {
System.out.println(method+" invoke");
return method.invoke(target, args1);
});
Object o = enhancer.create();
System.out.println(o.hashCode());
generation gap(生成模式)
该模式会生成代码导出行为 再通过编程来丰富程序行为 只修改或扩展一次 而可以生成代码多次 win下的GUI设计好像就这么做的
问题:
需求变化导致生成代码的变化
解决方式一是警告禁止修改 二是计算代码差异重新生成 三则是隐藏生成的代码的细节 隔离变与不变