结构化设计模式

166 阅读5分钟

我的理解:所谓的结构化,就是根据对应的业务场景,通过实现、继承、组合等各种方式调整对象之间的结构来达到需求目的。结构化设计模式当中,代理模式、装饰器模式、外观模式在编码的形式上的风格都非常的类似,在学习的过程当中其实更应该关注设计模式对应解决的问题;另,代码是手敲的,可能存在错误

适配器模式

概念

  • 适配器模式是将一个接口A的功能,转换成接口B的功能。目的是提升接口A的复用性
  • 目的:降低coding成本

应用场景

  • 实际应用中多用于系统重构。在新的系统结构代码中,设计了新的接口,但是为了复用老系统结构中的接口服务,就可以采用适配器模式,将老系统结构中的接口适配都新的系统结构中

UML

适配器模式.png

code

  • Adaptee Object -> 输出250v电压
public class Adaptee {
    public Integer supplyInterPower() {
        return 250;
    }
}
  • Target 接口 -> 需要220v电压
public interface Target {
    //need 220v volatge
    public Integer supplyInnerPower();
}
  • Adapter -> 适配Apdatee,将250v电压转换成220v
public class Adapter implement Target {
    private Adaptee adaptee;
   
    public Integer supplyInnerPower() {
        return adaptee.supplyInterPower() - 30;
    }

}

组合模式

概念

  • 组合模式是将一组相似对象组合成一个单个对象来进行使用。通常是以树形结构出现,然后暴露根节点给客户端(使用方),客户端通过根节点调度这一组相似对象
  • 目的:降低客户端使用成本。操作一组对象转换成操作单个对象

UML

组合模式.png

应用场景

  • java.util.concurrent.CompletableFuture#allOf

code

  • Base Component
public interface Shape {
    public void draw();
}
  • Leaf Compnent
public class Circle implement Shape {
    public void draw() {
        System.out.println("draw a circle");
    }
}

public class Square implement Shape {
    public void draw() {
        System.out.println("draw a square");
    }
}

public class Triangle implement Shape {
    public void draw() {
        System.out.println("draw a triangle");
    }
}
  • Composite
    • 此处用List的形式,常见是树结构
public class Drawing implement Shape {
    
    private List<Shape> shapes;
    
    public void draw() {
        shapes.forEach(Shape::draw);
    }
}

代理模式

概念

  • 当对象不能够直接被访问的时候,增加代理类作为中间层

UML

代理模式.png

应用场景

  • jdk copy-on-write proxy

code

public interface Query {
    public String queryCertificateNo(String userName);
}

public class UnSafeQuery implement Query {
    
    private String certificateNo;
    
    public String queryCertificateNo(String userName) {
        return 
    }
}



public class ProxyQuery implement Query {
    
    private Query unSafeQuery;

    public String queryEncryptCertificateNo(String userName) {
        String no = unSafeQuery.queryCertificateNo();
        return "123" + no + "789";
    }
    
    public String queryCertificateNo(String userName) {
        throw new UnsupportedOperationException();
    }
}

装饰器模式

概念

  • 在不影响其它实例的场景下,动态的给其中一个实例添加更多功能,并且实例和实例之间可以随意组装其和代理模式的差别在于:代理模式是为了屏蔽真实对象,装饰器模式是为了增强对象

应用场景

  • 没有找到著名case

UML

装饰器模式.png

Code

  • Car
public interface Car {
    public void assemble();
}
  • BasicCar
public class BasicCar implements Car {
    public void assemble() {
        System.out.println("assemble basic car")
    }
}
  • CarDecorator
public class CarDecorator implements Car {
    
    //被装饰的对象
    protected Car car;
    
    public CarDecorator(Car car) {
        this.car = car;
    }
    
    public void assemble() {
        System.out.println("assemble basic car")
    }

}
  • SportsCar
public class SportsCar extends CarDecorator {
    
    public SportsCar(Car c) {
        super(c); 
    }
    
    public void assemble() {
        car.assemble();
        System.out.println("add sports element");
    }

}
  • LuxuryCar
public class LuxuryCar extends CarDecorator {
    
    public SportsCar(Car c) {
        super(c); 
    }
    
    public void assemble() {
        car.assemble();
        System.out.println("add luxury element");
    }
}
  • ClientDemo
    • 重点在客户端使用的时候随意组装
public class ClientDemo {
    public static void main(String[] args) {
        //1. 组装sports元素
        Car car = new SportsCar(new BasicCar());
        car.assemble();
        //2. 组装luxury元素
        Car newCar = new LuxuryCar(car);
        newCar.assemble();
    }
}

外观模式

概念

  • 向客户端隐藏系统复杂度,降低客户端使用成本,好处是子系统相对独立,而客户端使用简便

应用场景

  • 著名case: slf4j-api -> 大型facade

示意图

门面模式.png

Code

  • 没有源代码

亨元模式

概念

  • 对象维护在一个容器当中,避免构造相同对象,降低内存使用率。目的是为了避免重复建造对象,多体现在工厂模式当中

应用场景

  • Java中的String
  • 连接池技术

UML

Code

  • org.apache.tomcat.jdbc.pool.ConnectionPool
    • tomcat-jdbc ConnectionPool中维护了两个
    • BlockingQueue busy;
    • BlockingQueue idle;

桥接模式

概念

  • 桥接是用于把抽象化与实现化解耦,使得二者可以独立变化,防止通过继承发生类的个数爆炸的场景,注意,这只是一个相对的情况。具体场景可设想为:有一个图形接口Shape,通过继承实现接口,衍生了多个实现类,红色的正方形(RedSquare)和黄色的正方形(YellowSquare)等,为了满足不同的颜色和不同的形状的组合,会产生多个实现类,这个时候,可以通过桥接模式,将两个变化的元素抽离,让颜色和形状可以独立变化

  • 目的解耦抽象化的部分,保证顶层设计不变

应用场景

  • java.sql.DriverInfo

UML

桥接模式.png

Code

背景

  • Shape
public interface Shape {
    public void applyColor();
}
  • RedSquare
public class RedSquare implements Shape {
     public void applyColor() {
         //do something with red square
     }
}
  • YellowCircle
public class YellowSquare implements Shape {
    public void applyColor() {
        //do something with yellow circle
    }
}
  • 随着诉求的不断迭代,Shape的实现类个数,会呈现指数增长

运用桥接模式来拆解Shape

  • Shape
public abstract class Shape { 
    protected Color color; 
    public Shape(Color c){ 
        this.color=c; 
    } 
    abstract public void applyColor(); 
}
  • Color
public interface Color {
    public void supplyColor();
}
  • Square
public class Square extends Shape {

	public Square(Color c) {
		super(c);
	}

	@Override
	public void applyColor() {
            //do something with private member 'color'
	} 

}
  • Red
public class Red implements Color {

    @Override
    public void supplyColor() {
       //supply red
    } 

}
  • Yellow
public class Yellow implements Color {

    @Override
    public void supplyColor() {
       //supply yellow
    } 

}
  • Demo
public class Demo {

    public static void main(String[] args) {
        Shape RedSqaure = new Square(new Red());
        Shape YellowSquare = new Square(new Yellow());
        //后续诉求如果出现其他颜色的Sqaure,Square可以复用
        //后续诉求如果针对现有颜色需要提供其它形状,现有的Color的实现类可以独立变化
        //将颜色和形状解耦,保持独立变化,提高类的复用性
    }

}