1. 什么是设计模式(Design pattern)
设计模式代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的
2. 设计模式的分类
* 创建型模式(5种):工厂方法模式,抽象工厂模式,单例模式,建造者模式,原型模式
* 结构型模式(7种):适配器模式,装饰器模式,代理模式,外观模式,桥接模式,组合模式,享元模式
* 行为型模式(11种):策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式
3. 设计模式的原则
开闭原则(Open Close Principle)**
对扩展开放,对修改关闭
里氏代换原则(Liskov Substitution Principle)**
只有当衍生类可以替换掉基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生类也能够在基类的基础上增加新的行为
依赖倒转原则(Dependence Inversion Principle)**
这个是开闭原则的基础,**对接口编程**,依赖于抽象而不依赖于具体
接口隔离原则(Interface Segregation Principle)**
使用多个隔离的借口来降低耦合度
迪米特法则(最少知道原则)(Demeter Principle)**
一个实体应当尽量少的与其他实体之间发生相互作用,使得系统功能模块相对独立
合成复用原则(Composite Reuse Principle)**
原则是尽量使用合成/聚合的方式,而不是使用继承。继承实际上破坏了类的封装性,超类的方法可能会被子类修改
4. 装饰设计模式(Decorator Pattern)
装饰模式指的是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象
Decorator Pattern特点
装饰对象和真实对象有相同的接口
装饰对象包含一个真实对象的引用
装饰对象接受所有来自客户端的请求
装饰对象可以在转发这些请求以前或以后增加一些附加功能
Decorator Pattern适用
需要扩展一个类的功能
需要动态的给一个对象添加功能
需要增加由一些基本功能的排列组合而产生的非常大量的功能
当不能采用生成子类的方法进行扩充时
Decorator Pattern优点
比继承更加灵活机动
Decorator Pattern缺点
如果过度使用,会使程序变得很复杂
如果你要针对具体组件编程时,就应该重新思考你的应用架构,以及装饰者是否合适
Decorator Pattern原则
多用组合,少用继承
类应设计的对扩展开放,对修改关闭
Decorator Pattern实例代码
java
[AppleScript] 纯文本查看 复制代码 //定义一个接口, 和一个draw方法
public interface Shape {
void draw();
}
//实现Shape接口
public class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("Shape: Rectangle");
}
}
//实现Shape接口
public class Circle implements Shape {
@Override
public void draw() {
System.out.println("Shape: Circle");
}
}
//装饰
public abstract class ShapeDecorator implements Shape {
protected Shape decoratedShape;
public ShapeDecorator(Shape decoratedShape){
this.decoratedShape = decoratedShape;
}
public void draw(){
decoratedShape.draw();
}
}
//测试效果
public class DecoratorPatternDemo {
public static void main(String[] args) {
Shape circle = new Circle();
Shape redCircle = new ShapeDecorator(new Circle());
Shape redRectangle = new ShapeDecorator(new Rectangle());
System.out.println("Circle with normal border");
circle.draw();
System.out.println("\nCircle of red border");
redCircle.draw();
System.out.println("\nRectangle of red border");
redRectangle.draw();
}
}
```
Decorator Pattern应用场景
java io流就是装饰设计模式
5. 代理设计模式(Proxy Pattern)
为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用
Proxy Pattern优点
职责清晰
中介作用
高扩展性
Proxy Pattern代码
``` java
[AppleScript] 纯文本查看 复制代码 //定义接口
public interface Shape {
public void draw();
}
//实现接口
public class RealShape implement Shape{
@Override
public void draw() {
System.out.println("Shape: RealShape");
}
}
//使用代理对象实现接口
public class Proxy implements Shape{
@Override
public void draw{
//引用并创建真实对象实例,即”我“
RealShape realShape = new RealShape();
//调用真实对象的方法,进行代理
realSubject.draw();
//代理对象额外做的操作
this.proxyDraw();
}
//增强的额外操作
public void proxyDraw(){
System.out.println("Proxy Shape: RealShape");
}
}
public class ProxyPattern {
public static void main(String[] args){
Shape proxy = new Proxy();
proxy.draw();
}
}
```
Proxy Pattern应用场景(分类)
静态代理
可以做到在不修改目标对象的功能前提下,对目标功能扩展
需要定义接口或者父类,被代理对象与代理对象一起实现相同的接口或者是继承相同父类
动态代理
代理对象,不需要实现接口
代理对象的生成,是利用JDK的API,动态的在内存中构建代理对象
动态代理也叫做:JDK代理,接口代理
Cglib代理
也叫作子类代理,它是在内存中构建一个子类对象从而实现对目标对象功能的扩展
JDK的动态代理有一个限制,就是使用动态代理的对象必须实现一个或多个接口,如果想代理没有实现接口的类,就可以使用Cglib实现
Cglib是一个强大的高性能的代码生成包,它可以在运行期扩展java类与实现java接口
Cglib包的底层是通过使用一个小而块的字节码处理框架ASM来转换字节码并生成新的类
总结
在Spring的AOP中:加入容器的目标对象有实现接口,用JDK代理;目标对象没有实现接口,用Cglib代理
6. 装饰设计模式和代理设计模式的区别
装饰模式关注于在一个对象上动态的添加方法,代理模式关注于控制对对象的访问
代理模式代理和真实对象之间的的关系通常在编译时就已经确定,装饰者能够在运行时递归地被构造
代理不支持多层嵌套,代理采用了类的组合,而装饰采用了类的聚合
原有的不能满足现有的需求,对原有的进行增强即是装饰设计模式
同一个类而去调用另一个类的方法,不对这个方法进行直接操作即是代理模式
|