java提高之设计模式详解
对设计模式认识比较肤浅,需要总结的比较通俗,可能部分失真,等以后随着实践和认知能力的提升,对文章再行完善。
目标
- 设计模式的六大原则
- 设计模式的划分
- 构建者模式
- 装饰器模式
- 工厂模式
1. 六大原则
1. 单一职责原则
Single Responsibility Principle, SRP,一个类只负责一个功能领域的相应职责。也就是我们常说的“高内聚,低耦合”
2. 开闭原则
Open-Closed Principle,OCP:对扩展开发,对修改关闭
也就是尽量在不修改原有代码的情况下进行扩展
3. 里式替换原则
Liskov Substitution Principle,LSP:所有引用父类的地方必须能透明的使用其子类的对象。
在程序中尽量使用基类类型来对对象进行定义,在运行时再确定子类类型,用子类对象来替换父类对象。
算是实现开闭原则的重要方式之一,通俗的说:子类可以扩展父类的功能,但不能改变父类原有的功能
4. 依赖倒置原则
Dependency Inversion Principle,DIP:抽象不应该依赖于细节,细节应该依赖于抽象,也就是面向接口编程,而不是针对实现编程。
开闭原则是目标,里式替换是基础,依赖倒置是手段。
感觉和spring的DI有点联系,后续再思考。
5. 接口隔离原则
Interface Segregation Principle,ISP:使用多个专门的接口,而不适用单一的总接口,即客户端不应该依赖那些它不需要的接口
每个接口应该承担相对独立的角色,提供定制服务,当然接口也不能太小,灵活性会变差。控制好接口的粒度。
6. 迪米特法则
Law of Demeter,LoD, 也叫最少知识原则,LeastKnowledge Principle,LKP:一个软件实体应当尽可能少的与其他实体发生相互作用
也就是解耦合,降低系统的耦合度。
2. 分类
大致按照设计模式的应用目标分类,分为创建型、结构型和行为型
- 创建型模式,是对对象创建过程的各种问题和解决方案的总结,包括各种工厂模式(Factory, Abstract Factory)、单例模式(Singleton)、构建者模式(Builder)、原型模式(Prototype)
- 结构型模式,是对软件设计结构的总结,专注于类、对象继承、组合方式的实践经验。常见的有桥接模式(Bridge)、适配器模式(Adapter)、装饰器模式(Decorator)、代理模式(Proxy)、组合模式(Composite)、门面模式(Facade)、享元模式(Flyweight)等。
- 行为型模式,是从类或者对象之间交互、职责划分等角度总结的模式,常见有策略模式(Strategy)、解释器模式(Interpreter)、命令模式(Command)、观察者模式(Observer)、迭代器模式(Iterator)、模板方法模式(Template Method)、访问者模式(Visitor)
如果想快速了解各个模式的作用,可以参考 追MM与设计模式 https://www.geek-share.com/detail/2705496562.html
3. 常用模式
1. 单例模式
之前总结有,https://blog.csdn.net/wjl31802/article/details/91360815
单例模式最常见,必须掌握
2. 装饰器模式
1. 典型使用场景
IO框架里面,InputStream是个抽象类,标准类库中提供了FileInputStream、ByteArrayInputStream等各种不同的子类,分别从不同角度对InputStream进行功能扩展。
2. 概念
本质上是包装同类型实例。我们对目标对象的调用,通过包装类覆盖过的方法,迂回调用被包装的实例,实现增加额外逻辑的目的,也就是“装饰”。
如BufferedInputStream为输入流增加了缓存。
优点:装饰类和被装饰类可以独立发展,不会耦合,是继承的一个替代模式
缺点:多层装饰较为复杂
使用场景:1. 扩展一个类的功能 2. 动态增加功能或撤销功能
3. 代码实现
为长方形和圆添加红边装饰
主要有几个类
接口
public interface Shape { void draw(); }
实现类
public class Rectangle implements Shape { @Override public void draw() { System.out.println("Shape: Rectangle"); } }
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; } @Override public void draw() { decoratedShape.draw(); } }
创建实体装饰类
public class RedShapeDecorator extends ShapeDecorator { public RedShapeDecorator(Shape decoratedShape) { super(decoratedShape); } @Override public void draw() { decoratedShape.draw(); setRedBorder(decoratedShape); } private void setRedBorder(Shape decoratedShape){ System.out.println("Border Color: Red"); } }
实例,用RedShapeDecorator装饰Shape对象
public class DecoratorPatternDemo { public static void main(String[] args) { Shape circle = new Circle(); ShapeDecorator redCircle = new RedShapeDecorator(new Circle()); ShapeDecorator redRectangle = new RedShapeDecorator(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(); } }
3. 构建者模式
1. 概念
比较优雅的解决构建复杂对象的麻烦,这里的“复杂”指的是类似需要输入的参数组合较多。如果用构造函数,需要为每一种可能的组合实现相应的构造函数,代码阅读星和可维护性差。
实质:从结构上把对象的使用逻辑和创建逻辑相互独立,隐藏对象实例的细节,为使用者提供更加规范、统一的逻辑。
典型的构造者模式,通常会被实现成fluent风格的API,也叫方法链。
以我们最常见的StringBuilder为例,append方法里面可能写String、char[ ]、int、long等等,该构建者为我们提供了统一的append方法,无需再写各种构造方法。非常方便。它的append后边可以再加其他方法,形成链。
2. 代码实现
public class Student { private int id; private String name; private String password; private String sex; private String address; // 构造器尽量缩小范围 private Student(){} private Student(Student origin){ // 拷贝一份 this.id = origin.id; this.name = origin.name; this.password = origin.password; this.sex = origin.sex; this.address = origin.address; } // getter/setter public static class Builder{ private Student target; public Builder(){ target = new Student(); } public Builder name(String name){ target.name = name; return this; } public Builder password(String passwd) { target.password = passwd; return this; } public Builder sex(String sex) { target.sex = sex; return this; } public Builder address(String address) { target.address = address; return this; } public Student build(){ return new Student(target); } } }
使用的话,
Student s = new Student.Builder().name("cc").password("123").sex("男").address("北京东长安街").build();
4. 工厂模式
最常见,创建对象的最佳方式,解耦
贴近实战,直接看spring的beanFactory工厂的诞生,自定义实现(也用到了单例模式)
public class MyBeanFactory { // 定义一个properties对象 private static Properties properties; // 静态代码块为对象赋值 static { InputStream in = MyBeanFactory.class.getClassLoader().getResourceAsStream("bean.properties"); properties = new Properties(); try { properties.load(in); } catch (IOException e) { throw new ExceptionInInitializerError("初始化properties失败"); } } public static Object getBean(String beanName){ Object bean = null; // 根据beanName获取对象 String beanPath = properties.getProperty(beanName); try { // class.forName("全类名")获取class对象 bean = Class.forName(beanPath).newInstance(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } return bean; } }
这样的工厂貌似可以实现功能,但是不是单例模式,每次都得到有个船新😭的对象,很显然不符合我们的期望,效率较低
public class MyBeanFactory { // 定义一个properties对象 private static Properties properties; // 用一个map容器来存储这些对象 private static Map<String,Object> beans; // 静态代码块为对象赋值 static { InputStream in = MyBeanFactory.class.getClassLoader().getResourceAsStream("bean.properties"); properties = new Properties(); try { properties.load(in); } catch (IOException e) { throw new ExceptionInInitializerError("初始化properties失败"); } // map进行初始化 beans = new HashMap<String, Object>(); // 获取properties里面的key Enumeration<Object> keys = properties.keys(); while(keys.hasMoreElements()){ // 得到每一个key String key = keys.nextElement().toString(); // 得到对应的beanPath String beanPath = properties.getProperty(key); Object value = null; // 获取value的object try { value = Class.forName(beanPath).newInstance(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } // 将key和value存到map中 beans.put(key,value); } } }
TODO
- Java IO详解(两种设计模式的分析)
- Java开发中的23种设计模式详解
- Java开发中的23种设计模式详解
- Java中23种设计模式详解
- android java 设计模式详解 Demo
- Java开发中的23种设计模式详解
- Java研究之学习设计模式-抽象工厂模式详解
- Java设计模式之五(单例模式详解)
- Java开发中的23种设计模式详解
- Java开发中的23种设计模式详解
- Java开发中的23种设计模式详解
- Java开发中的23种设计模式详解
- Java中的23种设计模式 详解
- JAVA:23种设计模式详解(转)2
- Java开发中的23种设计模式详解
- Java开发中的23种设计模式详解
- Java开发中的23种设计模式详解
- Java中23种设计模式详解
- Java中23种经典设计模式详解
- Java开发中的23种设计模式详解