随看随记
七大设计原则
- 编写软件过程中,程序员面临着来自耦合性,内聚性以及可维护性,可扩展性,重用性,灵活性等多方面的挑战,设计模式是为了让程序(软件),具有更好
- 代码重用性(即:相同功能的代码,不用多次编写
- 可读性(即:编程规范性,便于其他程序员的阅读和理解
- 可扩展性(即:当需要增加新的功能时,非常的方便,称为可维护
- 可靠性(即:当我们增加新的功能后,对原来的功能没有影响
- 使程序呈现高内聚,低耦合的特性
单一职责原则
- 我认为是使用功能的原子性
- 每个类只用一个职责,类似于数据库的第一范式,类仅有原子的作用。
- 当一个类有多个职责是,将这个类的功能进行拆分,或者对类中的方法进行分类修改。
- 主要还是为了解耦。
- 降低类的复杂度,一个类只负责一项职责。
- 提高类的可读性,可维护性
- 降低变更引起的风险
- 通常情况下,我们应当遵守单一职责原则, 只有逻辑足够简单,才可以在代码级违反单一职责原则;只有类中方法数量足够少,可以在方法级别保持单一职责原则
接口隔离原则
- 我认为是实现功能的原子性
- 我认为是要实现接口的原子性,一个接口仅仅实现自己需要的原则的一部分。通过一个类实现多个接口,来实现一个类的多种功能。
- 接口的功能不需要很大,否则会导致功能冗余。
- 一个类依赖(调用)了一个接口,这个接口应该是仅仅具有这个类的职责,而不应该有多余的职责。
- 一个类对另一个类的依赖应该建立在最小接口之上。
- A依赖B实现的接口,C依赖D实现的接口。A仅仅需要123方法,C需要145方法,如果按下面的这个图实现的话,则会导致B实现了4,5无用方法,D实现了2、3无用方法。

- 应该修改成这样,接口根据需要拆分成三个接口,B实现1、2接口,D实现1、3接口。这样A调用B时,不会有多余的4、5方法。C调用D时不会有多余的2、3方法。

依赖倒转原则
- 依赖指的是方法的输入参数。
- 我认为是实现了输入与方法实现的解耦
- 通过接口实现的方式,来实现的。
- 依赖倒转原则(Dependence Inversion Principle)是指:
- 高层模块不应该依赖低层模块,二者都应该依赖其抽象
- 抽象不应该依赖细节,细节应该依赖抽象,细节指的是实际的对象,抽象指的是接口等规范。
- 依赖倒转(倒置)的中心思想是面向接口编程
- 依赖倒转原则是基于这样的设计理念:相对于细节的多变性,抽象的东西要稳定的多。以抽象为基础搭建的架构比以细节为基础的架构要稳定的多。在java中, 抽象指的是接口或抽象类,细节就是具体的实现类
- 使用接口或抽象类的目的是制定好规范,而不涉及任何具体的操作,把展现细节的任务交给他们的实现类去完成
依赖倒转的反例

- 仅仅能接收Email,不能接收weixin等,需要有一个接口来解耦对特定类的依赖。这里的IReceiver表示所有的能够接收信息的对象要实现的接口。

依赖倒转的的实现方式有三种
- 在下面三种方式种,IOpenAndClose都是对象相应的需要实现的功能,对于方法执行对象都要接收一个统一的接口ITV,处理的重点在于如何将这个实现了接口(ITV)的对象传入我们要执行或调用的方法。
- 接口传递:通过方法的输入接收接口对象。
- 构造方法传递:
- 通过构造函数传进来的接口对象的方法。


- setter方式传递(SpringIOC):
- 通过setter()的方式接收接口对象。
里氏替换原则
- 父子方法功能要相同
- 子类和父类在方法的功能上完全相同时,才能使用里氏替换原则。强调的是父类与子类相同方法之间的透明性,是一种面向对象继承的一种原则。
- 在子类种尽量不要重写父类已实现的方法。
- 通常的做法是将这两个类都继承一个更大的基类baseClass,将原来的继承关系区掉,使用依赖,聚合,组合等方法来解决问题。
里氏替换原则反例
- 因为B继承了A,同时也继承了A方法,所以我们会理所当然的认为,fun1是实现的同一个功能,这样在我们使用的时候会误把B的fun1,也当作A的fun1方法,导致了问题。

解决方案
- 将B进行升级,不再成为A的子类,而是和A平级,这样就不会有人认为A和B的fun1方法是一个方法。如果我们依然想使用A类的方法,就可以使用聚合的方式,通过调用a.fun1()来实现,或者使用依赖fun2(A a)的方式来解耦。

开闭原则
- p16 ,自己看吧, 不太好描述。
- 对提供方扩展开放,对使用方修改关闭,即当要实现功能拓展的时候,需要尽量不要让使用方感受到修改的变化。
- 尽量通过拓展的方式而不是修改的方式。
- 视频中的解决方式是抽象出了一个公共抽象方法,来解决了这个问题。
迪米特法则
- p19 ,自己看吧, 不太好描述。
- 降低类与类之间的耦合性,我感觉就是自己的类的事情自己做,不要放到其他的类中去做。目的是提高内聚,减少耦合。
- 一个对 象应该对其他对象保持最少的了解
- 类与类关系越密切,耦合度越大
- 迪米特法则(Demeter Principle)又叫最少知道原则,即一个类对自己依赖的类知道的越少越好。也就是说,对于被依赖的类不管多么复杂,都尽量将逻辑封装在类的内部。对外除了提供的public方法,不对外泄露任何信息
- 迪米特法则还有个更简单的定义:只与直接的朋友通信
- 直接的朋友: 每个对象都会与其他对象有耦合关系,只要两个对象之间有耦合关系,我们就说这两个对象之间是朋友关系。耦合的方式很多,依赖,关联,组合,聚合等。其中,我们称出现成员变量,方法参数,方法返回值中的类为直接的朋友,而出现在局部变量中的类不是直接的朋友。也就是说,陌生的类最好不要以局部变量的形式出现在类的内部。
合成复用原则
- 尽量使用合成/聚合的方式,而不是使用继承的方式。
- 当A与B无关时,B仅仅想使用A的方法,这样就会导致,当对A进行扩展时,B不想要扩展,但是也会被动扩展。这不是我们想要的,因此使用依赖、组合、聚合的方式来进行解决。

- 依赖(方法传输参数)

- 聚合(通过setter注入属性的方式)
- 组合(通过构造函数注入的方式)

七大原则的核心思想
- 解耦:尽量减少不同类之间的侵入关系,尽量做到一个类修改不影响其他类。
- 复用:将共同有的方法拆解出来,不需要变化的代码混在一起。
- 抽象:要面向接口编程,对能够实现接口规范的都可以,而不要面向实现编程,这样就会导致仅仅针对某一个实例,而不是针对一批实例,导致服复用性差。(控制反转的主要思想)
UML类图
-
依赖:方法调用
-

-
继承:extend
-
实现:implement
-
组合:属性和对象创建是不可分离的,构造方法注入属性(组装乐高)
-
聚合:属性和对象创建是可以分离的,set注入属性(一把筷子)

设计模式分类
- 创建型模式:单例、抽象工厂、原型、建造者、工厂模式。
- 结构型模式:适配器模式、桥接模式、装饰器模式、组合模式、外观模式、享元模式、代理模式。
- 行为型模式:模板方法模式、命令模式、访问者模式、迭代器模式、观察者模式、中介者模式、备忘录模式、解释器模式、状态模式、策略模式、责任链模式。
创建型模式
- 以产生什么样的对象为重点
单例模式(SpringIOC Singleton)
- 很多对象仅仅需要一个就可以,并不需要频繁的创建销毁,这样可以节省内存和释放JVM资源
- 例如我们仅仅需要一个factory对象就可以了
- 如果private static Singeton instance 在懒汉式中不可以使用final,因为final后面必须紧跟着初始化。
- 单例模式创建对象的步骤:
- 私有化构造函数
- 类内部创建对象
- 提供一个共有静态方法,对外返回实例对象。
饿汉式 - 静态变量
- 静态的作用是在类加载的时候直接进行处理。
- 静态方法使用的变量必须是静态变量。
class Singeton{
private Singeton(){
//......
}
private final static Singeton instance = new Singeton();
public static Singeton getInstance(){
return instance;
}
}
饿汉式 - 静态代码块
class Singeton{
private Singeton(){
//......
}
private static Singeton instance;
static{
instance = new Singeton();
}
public static Singeton getInstance(){
return instance;
}
}
懒汉式 - 线程不安全
class Singeton{
private Singeton(){
//......
}
private static Singeton instance;
public static Singeton getInstance(){
if(instance == null) {
instance = new Singleton();
}
return instance;
}
}
懒汉式 - 同步类
class Singeton{
private Singeton(){
//......
}
private static Singeton instance;
public static synchronized Singeton getInstance(){
if(instance == null) {
instance = new Singleton();
}
return instance;
}
}
懒汉式 - 同步代码块 DCL(Double Check Lock)
class Singeton{
private Singeton(){
//......
}
private static volatile Singeton instance;
public static Singeton getInstance(){
if(instance == null) {
synchronized(Singeton.class){
if(instance == null) {
instance = new Singleton();
}
return instance;
}
}
}
}
懒汉式 - 静态内部类
- 当外部类被装载的时候,内部类不会被装载。因此是懒汉式。
- 因为也是通过类装载的方式解决的,因此是线程安全的。
class Singeton{
private Singeton(){
//......
}
private static class SingletonInstance {
private static final Singeton INSTANCE = new Singeton();
}
public static Singeton getInstance(){
return SingletonInstance.INSTANCE;
}
}
懒汉式 - 枚举
- 枚举默认不会被序列化,构造方法默认为私有且无法通过反射的方式变成公有。
- 枚举类中的每一个枚举项都是一个常量对象,
enum Singeton{
INSTANCE;
// 当没有写构造函数时,默认是下面的私有构造方法,去构造静态变量。
//private Singleton(){}
public void fun(){
//.......
}
}
反射
- 反射能够破坏单例的原因时可以拿到私有的构造方法,通过修改构造方法权限的方式,破坏单例。
- 饿汉式可以通过在构造函数中判断是否为空来,阻止反射的破坏。
private Singleton(){
if(singleton != null)
throw new RuntimeException("不允许反射访问");
}
- 但是DCL不可以通过标识位的方式,因为有可能通过反射构造方法而不会通过getInstance()方法。
private Singleton(){
boolean flag = false;
private Singleton(){
if(singleton != null)
throw new RuntimeException("不允许反射访问");
flag = true;
}
序列化
- 在反序列化的情况下,会自动创建一个新的对象,而不会使用原来的对象。
- 可以通过增加ReadResolve方法来避免创建新的对象。
public Object readResolve() throws ObjectStreamException {
return singleton;
}
枚举类不会被影响
- 枚举类是不会被反射。
- 枚举类在序列化时不会序列化枚举类对象,仅仅会序列化枚举类的对象的名字(INSTANCE这个字符串)。
工厂模式(BeanFactory)
- 目的在于不需要知晓具体构造情况。
- 我认为原型模式和工厂模式都是为了获取大批量对象,原型模式是在有已知对象的情况下,通过clone()方式从而不需要知道对象的实际情况。
- 工厂模式是在将工厂参数设计好以后,不需要知道对象是如何被创建的。
- 目的在于将对象的获取与对象的使用进行分离。
- 使调用者不需要关注对象是如何创建的。
- 任何可以得到对象的方法或者类都可以成为工厂。
- 目的在于获得一批对象,同时不用去关注对象创建的细节。
- 单例也是一种工厂。
简单工厂

- 一个能够得到创建对象的方式,就是简单工厂。
静态工厂
- 在这个类中通过静态的方法来创建对象的方法叫做静态工厂。
工厂方法
- 在产品的维度上扩展方便,只要实现了Factory的所有的工厂,都有了create()方法,因此子实现的所有的方法都会能创建对象,因此Factory就称为工厂方法模式。

- 在产品维度上扩展方便,例如可以扩展Car,Plane,Broom,Tank等。
- 只要实现了Factory就可以了。
抽象工厂
- 但是当Factory中不仅仅有一个方法的时候,这些方法所组成的一系列创造的对象称为产品族。
- 例如下面的图中一个抽象工厂中有武器,食物和交通工具三种。

- 当继承的时候,继承的对象就需要实现所有的方法,例如ModernFactory就会创建AK47、面包、汽车。MagicFactory就会创建魔法杖、红蘑菇、扫帚。
- 但是ModernFactory中不能创造魔法棒,MagicFactory不能创造AK47。
- 即不同簇之间创造的对象是不同的,具有隔离性的。
- 因此想要扩展一个产品族时,就需要抽象工厂了。
- 但是如果仅仅扩展一个同类型的工厂,仅仅需要工厂方法就可以了。
- 在QQ的换肤操作类似,仅仅切换另一个实现工厂就可以实现一键换肤。
- 产品族,相当于这一族产品的所有的动作都是一系列的固定的,不同的产品族之间是不会交叉的。
- 抽象工厂(BeanFactory)隔离不同的产品族,因为每个bean对象都要求走bean的生命周期。
- 工厂方法(FactoryBean)只能生产一个产品,我们想要的bean的工厂。

- 当使用魔法世界的东西的时候,直接new一个magicFactory就可以了。
原型模式(克隆羊)(bean prototype)
- 强调在不知晓对象细节的情况下,依旧得到对象的同类,与new一个对象的本质区别。
- 我感觉这个视频没说到点子上,原型模式的目的在于在不知晓对象具体构造的情况下,能够创造出对象一样的个体。
- String类型不需要深拷贝,以为Java有常量池,直接到缓冲池中拿对应的字符串就行了,但是如果String被封装到一个对象(包括new一个String对象)中就需要进行深拷贝了,因为拷贝前后的对象是指向同一个属性对象的。

- p1的Location 和p2的location不是一个location,但是两个location指向的对象是一个对象。
- 因为在调用clone()的情况时,并不需要像new一样输出各种构造参数,而是仅仅调用clone()方法就可以了。
- clone()不是重点,clone()仅仅是JDK提供的方便我们利用原型模式的一种方法,和动态代理是一样的。

- 在使用clone()时,必须要实现cloneable接口才可以。如果使用浅拷贝则直接使用JDK自带的就可以,如果使用深拷贝则需要进一步处理。
浅拷贝和深拷贝
- JDK中默认的clone()方法是浅拷贝,仅仅会拷贝引用地址,而不会拷贝对象属性。如果需要对象的对象属性也需要拷贝,则需要进行处理。

clone方式
- 把对象属性的对象也进行clone()处理,这样就可以实现对象属性的拷贝。
- 这里的deepCloneableTarget是一个对象属性,因此在进行克隆的时候,把对象也进行克隆就可以了。
- 但是这种方法在对象属性特别多的情况下,就会导致另外clone()的对象特别多,因此并不推荐这种写法。

序列化方式
- 通过序列化的方式进行创建对象。要实现Serializable接口。
public CloneTest deepClone() throws IOException{
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
// 向内存的缓冲区写入二进制字节数组
oos.writeObject(this);
// 从指定的缓冲区拿到字节数组
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
CloneTest cloneTest = null;
try {
// 将字节数组转化成对象
cloneTest = (CloneTest) ois.readObject();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally{
ois.close();
bis.close();
oos.close();
bos.close();
}
return cloneTest;
}
- 其原理还是IO流序列化的readResolve()方法,会默认自动创造一个新的对象。
建造者模式(盖房子)(Mybatis sqlSessionBulider)

- 将建造过程进行解耦,接口或抽象类仅仅提供建造流程,流程的具体实施,由各自的实际建造者决定。
- 建造者注重的是建造对象的特异性,工厂模式注重的是如何获得一批产品。
- ==建造者的目的是通过我们的既定流程,使用具体的建造者得到一个具体的对象。外观模式是通过我们的既定方法,使用具体的对象得到一个实际的方法实现来调用。==外观模式不强调得到一个对象,而是强调既定方法独自实现。
- 建造者模式强调的是,当建造一个对象有很多不同的过程要素,可以通过设置不同的参数,来成为不同的实际构造者(concreteBulider),通过不同的构造者来建造对象。


- Product (产品角色,你要得到的类对象) : 一个具体的产品对象。
- Builder (抽象建造者,你创建一个对象必须要有的流程,不会有具体的实现) :创建一个Product对象的各个部件指定的接口。
- ConcreteBuilder (具体建造者,每个流程都有具体的实施) :实现接口, 构建和装配各个部件。
- Director (指挥者,调用build方法,建造一个producet方法) :构建"一个使用Builder接口的对象。它主要是用于创建一个复杂的对象。它主要有两个作用,一是:隔离了客户与对象的生产过程,二是:负责控制产品对象的生产过程。
结构型模式
- 让类与类之间可以协同工作
适配器模式(电压问题)(SpringMVC HandlerAdapter)
- 强调的是两个类之间,如果不能调用,则需要增加一个缓冲层来辅助进行调用。
- 重点在于适配器两端的解耦。


类适配器

- 通过继承类来实现对220v的适配
- 由于是继承关系,因此增加了Adapter和Voltage220V之间的耦合性,因此在对象适配器中,就是通过聚合的方式来减少Voltage220V耦合性。
- 其输出都是5v,重点在于实现了输出为5V的接口
对象适配器
-

-

-
通过聚合的方式对220V进行适配。
接口适配器
- 接口适配器更像定义一个规范,对于适配器的输出有这默认的n种,如果想要适配的输出在这n种,就直接重写就可以了,否则需要另加新的适配方式。
- 对于接口适配器中抽象类内所有的方法都是缺省的,具体的实现看具体我们需要什么样的适配方法。


桥接模式(双维度扩展 JDBC)
-

-
桥接模式的目的是防止类爆炸的。
-
 -

-
这样聚合以后,就时收到了Warm + Gift 。 如果想要更换,则就是cool + book等,这样通过抽象和实现的分别扩展,来减少类爆炸。
-
使用桥接有m个实现n个抽象,则 可以有n*m的具体实现,如果仅仅用继承则 要有n * m 个类。
-

-
具体做法是将抽象类和实现类从继承关系转化为聚合关系。
-
分成了两部分,一部分是抽象的部分,一部分是具体的实现。通过将抽象和实现分离开,这样可以在对抽象扩展是不会影响实现类,实现类增加实现时,不会影响抽象类,然后实现双维度扩展。
装饰者模式(星巴克咖啡)(Mybatis CachingHandler)
- 用聚合代替继承
- 在原有的对象的基础上增加一点装饰。

- 会在类的内部封装一个decorator,这个decorator就是我们想要装饰的对象,在这个类中,增加一个方法,通过对这个decorator对象进行操作,从而实现对decorator的装饰。
- decorator可以传入所有的实现GameObject类的对象,并对其进行装饰。
- Mybatis中通过decorator,对baseHandler的三个实现类,simpleHandler、reuseHandler、batchHandler进行了封装,并对其进行了二级缓存的装饰。
组合模式Composite(树状结构模式)


- 就是一棵树
- 对于branch节点,可能会有很多子节点,通过递归的方式去处理这种情况。HashMap中的拉链法。
享元模式(共享元数据)(连接池的思想)
- 在池中的对象进行复用,不要每次需要一个对象就去创建,用完销毁。在用完之后,回收到池子中,等到下一次进行复用。

门面模式(外观模式)(Mybatis的BaseHandler)
- 对外,类似于处理一个黑匣子。
- 各个方框之间的关系错综复杂,如果要实现一个行动,则需要去寻找很多个方框对象来进行协调。
- 因此抽象出来一个外观(矩形),作为接口,我们直接调用这个接口的方法,而黑匣子中的具体实现,我们不去关注。


调停者模式(中介者模式)(消息中间件)
- 对内
- 当内部的对象过于复杂的情况下,使用一个中介,来协调各个对象之间的调用。类似于交换机的实现。

行为型模式
- 限制类的行为,使其符合既定的规范
策略模式(Stratery)(Comparator)(ThreadPoolExecutor)
- 封装的是做一件事情时,不同的执行方式
- 通常对于策略模式来说,通常会写几个默认的执行策略,然后直接调用这些策略就好。(例如线程池中的拒绝策略)
- comparator是策略模式,comparable不是策略模式。

- 对于只有实现了Comparable的类才能进行比较,通过重写其中的compareTo()方法,来实现比较的方式。主要的目的是为了提供两个类比较的方式。
- 但是当比较的方式增多时,对于不同的对象来说,不同的属性来说,比较的策略往往是不同的。因此就需要Comparator来表示需要比较的策略。
- 每个实现的comparator就是一个策略。
责任链模式()
- 实现对递进状态事件处理的解耦。
- 博客
- 可以通过将我们需要的事件插入到责任链中,来进行处理。插入责任,链,则表示在之前的都处理过,在确定是否处理本次的事件。
- 通过设置我们的事件的插入的位置,来判断我们在什么时候需要处理该事件。( 每个实现类继承了Handler)
- 不同处理事件的方式是不同的,每一处理事件都会有自己的处理链,把所有的链连接在一起,一起去处理就可以。(HandlerChain也继承了Handler)
- 一个处理链的内部都是自己的一系列处理逻辑。
- 有的是需要处理的进行处理,不需要处理的就不进行处理。


命令模式
- 当很多个模块都具有类似功能但具体实现不同的方法时,可以将其封装起来,其子对象调用其中相应的已经实现的方法就可以了。
- 例如在word中,文本、图像等都具有复制、插入、删除、撤回的功能,因此把这四个功能封装起来,放到接口Command中,当我们调用的时候,就可以直接调用Command的对应子类的方法就可以了。

- 命令+组合 -> 宏命令,一个命令套另一个命令。
- 命令+责任链 -> 多次撤销,每次操作时都会记录到Chain中,当需要撤回时,只要对责任链进行执行就行。
- 命令+备忘录 ->

模板方法(JDBCTemplate)

- 模板方法中会规定一个方法的流程,具体的子类会实现这个流程中具体的方法,来实现这个是实现类的这个特异化功能。
- 这个流程就是这个模板方法的模板

迭代器模式(List)
- hasNext()有下一个吗 + next()输出下一个

- 遍历用的
- ArrayList扩容每次扩大到1.5倍
访问者模式(编译器)
- 访问结构固定的
- 每个Visitor实现自己的accept()方法,让自己去处理实现的accept()的方式

观察者模式(Obsever)(Spring Event)
- 在很多系统中,Observer模式往往和责任链共同负责对于事件的处理,
其中的某一个Observer是否将事件进一步传递。 - 观察者主要有三个对象,事件源(婴儿),观察者(父母和狗),事件(哭)。当事件源(婴儿)触发事件(哭)时,观察者(父母)做出相应的动作。而且在事件源中需要注册观察者有哪些,观察者所进行的一系列动作一般由责任链模式来执行。
- 一般和责任链一起用,当一个事件发生时,通常会有一系列的观察者做出相应的动作,从而和责任链模式一起走流程

观察者
- 对于观察者来说,主要是实现了针对事件发生的方法。
- 根据事件传进来的参数,来自定义事件的处理方式。

事件源
- 对于事件源来说,要维护一个观察者列表,所有继承了observer都会可以放到检观察者列表中。

- 这个add()方法可以对外封装出去,来增加观察者,来维护观察者列表。
事件
- 对于事件来说,事件本身也有很多的状态,一般都会有事件源,getSource(),因为对于观察者来说,有事件源才好处理事件。
- 一般会抽象处一个事件本身,在上面的例子中,行了触发哭的时候会有很多状态,时间,或者哭的位置。
- 事件源对象如何传递给观察者,就在事件中增加一个事件源。一般Event都会有getSource方法来获取事件源。

- 事件是可以成体系的。

代理模式(SpringAOP)
- 聚合代替继承,通过Tank的对象来代替继承Tank,从而能够把tank对象封装起来进行使用。

- Proxy通过对聚合的对象使用Movable接口类,而不是具体对象,则会对所有的Movable对象都可以实现。

- 动态代理类相当于生成了最上面的TankTimeProxy对象

JDK动态代理源码

- this 生成的$Proxy对象,m3 表示被代理的方法,args表示参数

- 整个流程包括两部分:1和2表示创建代理类,3表示执行代理方法:
- 调用生成代理类
- 代理类接收InnovationHandler,来方便后面调用它。
- 通过调用InnovationHandler的invoke方法,先去执行before的方法,然后执行原生的方法,后去执行after的方法,来进行代理。
CGLIB
- 注意在CGLIB中应该调用的是methodProxy的invokeSuper方法,这样才表示调用了目标类的对应方法。

备忘录模式(快照)
- 事务回滚
状态模式(State)
- 根据状态决定行为

解释器模式
- 略

本文详细介绍了Java设计模式的七大原则,如单一职责、接口隔离、依赖倒转、里氏替换、开闭原则、迪米特法则、合成复用原则,并提供了UML类图。文章还详细探讨了创建型模式、结构型模式和行为型模式的各类模式,如单例、工厂、原型、适配器、装饰器、组合、策略、责任链等,以及它们在实际开发中的应用。






1106

被折叠的 条评论
为什么被折叠?



