重庆网站建设推广公司哪家好,上海网站推广多少钱,物流网站建设案例,麻涌公司网站建设公司三、设计模式
3.1 设计模式简介
软件设计中的三十六计是人们在长期的软件开发中的经验总结是对某些特定问题的经过实践检验的特定解决方法被广泛运用在 Java 框架技术中
3.1.1 设计模式的优点
设计模式是可复用的面向对象软件的基础可以更加简单方便地复用成功的设计和体系…三、设计模式
3.1 设计模式简介
软件设计中的三十六计是人们在长期的软件开发中的经验总结是对某些特定问题的经过实践检验的特定解决方法被广泛运用在 Java 框架技术中
3.1.1 设计模式的优点
设计模式是可复用的面向对象软件的基础可以更加简单方便地复用成功的设计和体系结构帮助开发者做出有利于系统复用的选择避免损害系统复用性的设计使其他开发者更加容易理解其设计思路便于团队交流
3.1.2 设计模式分类
GoFGang of Four四人组设计模式分为23种
范围/目的创建型模式结构型模式行为型模式类模式工厂方法(类适配器模板方法解释器对象模式单例原型抽象工厂建造者代理(对象适配器桥接装饰外观享元组合策略命令职责链状态观察者中介者迭代器访问者备忘录
3.1.3 面向对象设计原则
单一职责原则
一个类应该有且仅有一个引起它变化的原因一个类应该只负责一个职责
开闭原则
对扩展开放对修改关闭
里氏替换原则
引用基类的地方必须能透明地使用其子类的对象可以用来判断继承关系是否合理
依赖倒置原则
依赖于抽象而不依赖于具体实现针对接口编程
接口隔离原则
尽量将庞大臃肿的接口拆分成更小更具体的接口接口中只包含客户感兴趣的方法
迪米特法则
又称最少知道原则一个软件实体应当尽可能少地与其他实体发生相互作用
合成复用原则
尽量使用组合/聚合的方式而不是继承关系达到软件复用的目的是 has-a 关系 3.2 简单工厂模式
如何解决类似“Service与某个具体Dao实现”耦合的问题
将创建工作转移出来避免在Service中创建具体的Dao实现类产生耦合 简单工厂模式又叫做静态工厂方法模式不属于 GoF 的23种设计模式之一可以理解为工厂模式的一个特殊实现 3.2.1 简单工厂模式依赖倒置原则
依据依赖倒置原则使用setter方法传递依赖关系减少Service对工厂类的依赖降低耦合
public class NewsServiceImpl implements NewsService {private NewsDao dao;public void setDao(NewsDao dao) {this.dao dao;}… …
}3.2.2 简单工厂参数
简单工厂模式可以根据参数的不同返回不同类的实例被创建的实例通常都具有共同的父类
// 创建NewsDao实例的工厂方法
public static NewsDao getInstance(String key) {switch (key) {case mysql:return new NewsDaoMySqlImpl();case oracle:return new NewsDaoOracleImpl();case redis:return new NewsDaoRedisImpl();default:throw new RuntimeException(无效的数据库类型 key DAO获取失败);}
}要创建的产品不多且逻辑不复杂的情况可以考虑简单工厂模式
简单工厂模式包含如下角色
工厂Factory抽象产品Product具体产品Concrete Product 增加新的产品需要修改工厂方法的判断逻辑不符合开闭原则 3.3 工厂方法模式
3.3.1 实现方式
对简单工厂模式的进一步抽象工厂方法模式的主要角色如下
抽象产品Product抽象工厂Abstract Factory具体产品Concrete Product具体工厂Concrete Factory
3.3.2 代码案例
创建抽象工厂接口
public interface AbstractFactory {public NewsDao getInstance();
}为不同NewsDao实现创建相对应的具体工厂
// 以生产NewsDaoMySqlImpl实例的工厂为例
public class MySqlDaoFactory implements AbstractFactory {Overridepublic NewsDao getInstance() {return new NewsDaoMySqlImpl();}
}在测试方法中通过特定工厂生产相关的NewsDao实例
AbstractFactory factory new MySqlDaoFactory();
// 改变具体工厂可创建不同产品
NewsDao dao factory.getInstance();3.3.3 优缺点
优点
只需要知道具体工厂就可得到所要的产品无须知道产品的具体创建过程基于多态便于对复杂逻辑进行封装管理增加新的产品时无须对原工厂进行任何修改满足开闭原则
缺点
每增加一个产品就要增加一个具体产品类和一个对应的具体工厂类这增加了系统的复杂度 3.4 代理设计模式
单一职责原则的体现包含如下角色
抽象主题Subject真实主题Real Subject代理Proxy
实现方式总体上分为静态代理和动态代理
静态代理由开发者针对抽象主题编写相关的代理类实现编译之后生成代理类的class文件动态代理是在运行时动态生成的在运行时动态生成代理类字节码
3.4.1 基于接口的静态代理实现
// 抽象主题接口 - 图片
public interface Image {void display();
}// 真实主题类 - 真实图片
public class RealImage implements Image {private String filename;public RealImage(String filename) {this.filename filename;loadImageFromDisk();}private void loadImageFromDisk() {System.out.println(Loading image from disk: filename);}public void display() {System.out.println(Displaying image: filename);}
}// 代理类 - 图片代理
public class ImageProxy implements Image {private RealImage realImage;private String filename;public ImageProxy(String filename) {this.filename filename;}public void display() {if (realImage null) {realImage new RealImage(filename);}realImage.display();}
}// 调用代码
public class Client {public static void main(String[] args) {// 创建代理对象并显示图片Image image new ImageProxy(example.jpg);image.display();}
}3.4.2 代理模式优点分析
代理模式将客户与目标对象分离在一定程度上降低了系统的耦合度代理对象可以对目标对象的功能进行扩展目标对象和扩展功能职责清晰且不会产生耦合
3.4.3 动态代理
静态代理需要手工编写代理类存在以下弊端
目标对象API发生变化代理类也必须进行修改增加工作量且不符合开闭原则通过继承得到的代理类只能对一种类型进行代理组件较多时代理类的开发工作量巨大 动态代理提供了运行时动态扩展对象行为的能力能够依据给定的业务规则在运行时动态生成代理类 3.4.4 JDK 动态代理
从JDK 1.3版本开始引入
是面向接口的代理实现
要求被代理的目标对象必须通过抽象主题接口进行定义
核心API
java.lang.reflect.InvocationHandler接口 代理方法的调用处理程序负责为代理方法提供业务逻辑包含方法Object invoke(Object proxy, Method method, Object[] args) java.lang.reflect.Proxy类 负责动态创建代理类及其实例主要方法static Object newProxyInstance(ClassLoader loader, Class?[] interfaces, InvocationHandler h)
3.4.5 CGLIB 动态代理
如果被代理的目标对象不是通过接口进行定义的JDK 动态代理将无法实施
CGLIBCode Generation Library是一个功能强大高性能的代码生成库可以为没有实现接口的类提供代理原理是为需要代理的类动态生成一个子类作为其代理类 需要使用继承和重写机制CGLIB动态代理对于final类或final方法无能为力 从cglib https://github.com/cglib/cglib/releases下载所需的 jar 文件
cglib-nodep-x.x.x.jar
主要 API
net.sf.cglib.proxy.MethodInterceptor 接口 负责拦截父类的方法调用以便加入代理的业务逻辑包含方法 Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) net.sf.cglib.proxy.Enhancer 类 负责动态创建代理类及其实例主要方法 setSupperclass()setCallback()set…create()
3.4.6 JDK 和 CGLIB 动态代理的对比
JDK 动态代理面向接口代理只能对基于接口设计的目标对象进行代理CGLIB 动态代理可以通过继承方式实现不依赖接口但是不能代理 final 的类和方法