常用的设计模式

无望

设计模式 复习整理(仗剑走天涯)

常用的简单设计模式

工厂设计模式

工厂模式分为简单工厂模式,工厂方法模式和抽象工厂模式,它们都属于设计模式中的创建型模式。其主要功能都是帮助我们把对象的实例化部分抽取了出来,目的是降低系统中代码耦合度,并且增强了系统的扩展性。

还有一个很重要的原因,就是对象的创建过程比较复杂,使用工厂模式进行封装,同时可以屏蔽掉对象的复杂的创建过程

简单工厂设计模式

简单工厂模式最大的优点在于实现对象的创建和对象的使用分离,将对象的创建交给专门的工厂类负责,但是其最大的缺点在于工厂类不够灵活,增加新的具体产品需要修改工厂类的判断逻辑代码,而且产品较多时,工厂方法代码将会非常复杂

  • Factory 工厂角色

工厂角色负责实现创建所有实例的内部逻辑

1
2
3
4
5
6
7
8
9
10
11
12
public class FriendFactory {

public Friend friendName(String name){
if(name.contentEquals("胖子")){
return new FattyFriend();
}else if (name.contentEquals("SB铭")){
return new SBFriend();
}else{
throw new RuntimeException("没有此朋友");
}
}
}
  • Product 抽象产品角色

抽象产品角色是所创建的所有对象的父类,负责描述所有实例所共有的公共接口

1
2
3
4
5
public interface Friend {

public void play();

}
  • ConcreteProduct 具体产品角色

具体产品角色是创建目标,所有创建的对象都充当这个角色的某个具体类的实例

1
2
3
4
5
6
7
public class FattyFriend implements Friend {

@Override
public void play() {
System.out.println("胖子");
}
}
1
2
3
4
5
6
public class SBFriend implements Friend {
@Override
public void play() {
System.out.println("SB");
}
}
  • client
1
2
3
4
5
6
7
8
9
public class Client {

public static void main(String[] args) {

FriendFactory friendFactory = new FriendFactory();
Friend friend = friendFactory.friendName("SB铭");
friend.play();
}
}

简单工厂设计模式

工厂方法模式

  • factory 抽象工厂
1
2
3
4
5
public interface Factory {

public Friend Friend();

}
  • ConcreteFactory 具体工厂
1
2
3
4
5
6
7
8
public class FattyFriendFactory implements Factory{

@Override
public FattyFriend Friend() {

return new FattyFriend();
}
}
1
2
3
4
5
6
7
public class SBFriendFactory implements Factory {
@Override
public Friend Friend() {

return new SBFriend();
}
}
  • Product 抽象产品
1
2
3
4
5
public interface Friend {

public void play();

}
  • ConcreteProduct 具体产品
1
2
3
4
5
6
7
public class FattyFriend implements  Friend{

@Override
public void play() {
System.out.println("胖子");
}
}
1
2
3
4
5
6
public class SBFriend implements Friend {
@Override
public void play() {
System.out.println("SB");
}
}
  • client
1
2
3
4
5
6
7
8
9
public class Client {

public static void main(String[] args) {

Factory factory = new SBFriendFactory();
Friend friend = factory.Friend();
friend.play();
}
}

工厂方法模式
好处

此模式中,通过定义一个抽象的核心工厂类,并定义创建产品对象的接口,创建具体产品实例的工作延迟到其工厂子类去完成。这样做的好处是核心类只关注工厂类的接口定义,而具体的产品实例交给具体的工厂子类去创建。当系统需要新增一个产品是,无需修改现有系统代码,只需要添加一个具体产品类和其对应的工厂子类,使系统的扩展性变得很好,符合面向对象编程的开闭原则

缺点

工厂方法模式虽然扩展性好,但是增加了编码难度,大量增加了类的数量,所以怎么选择还是看实际的需求

抽象工厂模式

在有多个业务品种、业务、分类时,通过抽象工厂模式产生需要的对象是一种非常好的解决方式

1
2
3
4
5
6
7
public abstract class AbstractFactory {

public abstract AbstractManFriend manFriend();

public abstract AbstractGiriFriend giriFriend();

}
1
2
public abstract class AbstractGiriFriend{
}
1
2
public abstract class AbstractManFriend {
}
1
2
3
4
5
6
7
8
9
10
11
public class AFriendFactory extends AbstractFactory{
@Override
public AbstractManFriend manFriend() {
return new AManFriend();
}

@Override
public AbstractGiriFriend giriFriend() {
return new AGiriFriend();
}
}
1
2
3
public class AGiriFriend extends AbstractGiriFriend {

}
1
2
public class AManFriend extends AbstractManFriend{
}
1
2
3
4
5
6
7
8
9
10
11
public class BFriendFactory extends AbstractFactory{
@Override
public AbstractManFriend manFriend() {
return new BManFriend();
}

@Override
public AbstractGiriFriend giriFriend() {
return new BGiriFriend();
}
}
1
2
public class BGiriFriend extends AbstractGiriFriend {
}
1
2
public class BManFriend extends AbstractManFriend {
}
1
2
3
4
5
6
7
8
9
10
public class Client {

public static void main(String[] args) {

AbstractFactory abstractFactory = new AFriendFactory();
AbstractManFriend abstractManFriend = abstractFactory.manFriend();

System.out.println(abstractManFriend);
}
}

创建者模式

分离对象子组件的单独构造(由Buider来负责)和装配(由Director负责)。从而可以构造出复杂的对象。这个模式适用于:某个对象的构建过程复杂的情况下使用。

由于实现构造和装配的解耦。不同的构造器,相同的装配,也可以做出不同的对象;相同的构造器,不同的装配顺序也可以做出不同的对象。也就是实现了构建算法、装配算法的解耦,实现了更好的复用。

最典型的就是我们的StringBuilder和StringBuffer。

  • Builder:抽象建造者

  • ConcreteBuilder:具体建造者

  • Director:指挥者

  • Product:产品角色
    创建者模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
public class Lifecycle {

private String birth;

private String school;

private String work;

private String marriage;

private String die;

public String getBirth() {
return birth;
}

public void setBirth(String birth) {
this.birth = birth;
}

public String getSchool() {
return school;
}

public void setSchool(String school) {
this.school = school;
}

public String getWork() {
return work;
}

public void setWork(String work) {
this.work = work;
}

public String getMarriage() {
return marriage;
}

public void setMarriage(String marriage) {
this.marriage = marriage;
}

public String getDie() {
return die;
}

public void setDie(String die) {
this.die = die;
}

public static class Builder{

private final Lifecycle lifecycle = new Lifecycle();

public Builder builderBirth(String birth){
lifecycle.setBirth(birth + "我来到了这世间");
return this;
}

public Builder builderSchool(String school){
lifecycle.setSchool(school + "开始上学");
return this;
}

public Builder builderWork(String work){
lifecycle.setWork(work + "毕业开始工作");
return this;
}

public Builder builderMarriage(String marriage){
lifecycle.setMarriage(marriage + "***");
return this;
}

public Builder builderDie(String die){
lifecycle.setDie(die + "死去");
return this;
}

public Lifecycle builder(){
return lifecycle;
}
}

@Override
public String toString() {
return "Lifecycle{" +
"birth='" + birth + '\'' +
", school='" + school + '\'' +
", work='" + work + '\'' +
", marriage='" + marriage + '\'' +
", die='" + die + '\'' +
'}';
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Client {

public static void main(String[] args) {

Lifecycle lifecycle = new Lifecycle.Builder().builderBirth("2001-04-06")
.builderSchool("2006-09-01")
.builderWork("2023-07-01")
.builderMarriage("****")
.builderDie("某年某月某日")
.builder();

System.out.println(lifecycle);
}
}

创建者模式是一个对对象的构建过程“精细化”的构建过程,每个部分的构建可能是变化的,但是对象的组织过程是固定的,通过这种统一的创建方式,无疑增加了我们设计上的灵活性,当我们在构建复杂对象的时候,我们如果发现每个部分可能都是变化的,并且是多个不同的构建步骤的时候,我们可以考虑使用创建者模式

代理设计模式

代理的核心功能是方法增强

静态代理模式

抽象角色 : 一般使用接口或者抽象类来实现

真实角色 : 被代理的角色

代理角色 : 代理真实角色 ; 代理真实角色后 , 一般会做一些附属的操作

客户 : 使用代理角色来进行一些操作

静态代理的两种方式

  • 实现接口

不同对象实现相同接口

1
2
3
4
5
public interface Bossinterface {

public void project();

}
1
2
3
4
5
6
7
8
9
10
11
12
13
public class Boss implements Bossinterface {

private String name;

public Boss(String name) {
this.name = name;
}

@Override
public void project() {
System.out.println(name + "要做个项目");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Proxy implements Bossinterface {

private Boss boss;

public Proxy(Boss boss) {
this.boss = boss;
}

@Override
public void project() {
System.out.println("项目经理给我想法子");
System.out.println("策划给我设计");
boss.project();
System.out.println("程序员给我写");
System.out.println("运维给我善后");
}
}
1
2
3
4
5
6
7
8
public class Client {

public static void main(String[] args) {

Bossinterface bossinterface = new Proxy(new Boss("Boss"));
bossinterface.project();
}
}
  • 继承父类
1
2
3
4
5
public class Boss {
public void project(){
System.out.println("老板一个大饼我要做个新项目");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
public class Proxy extends Boss {

@Override
public void project() {

System.out.println("项目经理给我想法子");
System.out.println("策划给我设计");
super.project();
System.out.println("程序员给我写");
System.out.println("运维给我善后");

}
}
1
2
3
4
5
6
7
public class Client {

public static void main(String[] args) {
Proxy proxy = new Proxy();
proxy.project();
}
}

优点

公共的统一问题交给代理处理

公共业务进行扩展或变更时,可以更加方便

缺点

每个类都写个代理

动态代理模式

动态代理的代理类是动态生成的 ,静态代理的代理类是我们写的

动态代理分为两类 : 一类是基于接口动态代理 , 一类是基于类的动态代理

基于接口的动态代理—-JDK动态代理

基于类的动态代理–cglib

JDK源生动态代理

jdk动态代理的两个核心类

  • InvocationHandler
1
2
3
4
5
6
/** Invoke the given method with the args and return the result.
* This may result in a remote invocation.
* @param proxy The proxy used for this class (null if not using java.lang.reflect.Proxy)
*/
public Object invoke( Object proxy, final Method method,
Object[] args ) throws Throwable{}

proxy 调用该方法的代理实例

method 所述方法对应于调用代理实例上的接口方法的实例。方法对象的声明类将是该方法声明的接口,它可以是代理类继承该方法的代理接口的超级接口。

args 包含的方法调用传递代理实例的参数值的对象的阵列,或null如果接口方法没有参数。原始类型的参数包含在适当的原始包装器类的实例中,例如java.lang.Integer或java.lang.Boolean 。

  • Proxy
1
2
3
4
@CallerSensitive
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)throws IllegalArgumentException{}

loader 加载路径

interfaces 接口类 是个数组 可以是多个

InvocationHandler invocationHandler接口

1
2
3
4
5
public interface Bossinterface {

public void project();

}
1
2
3
4
5
public class Boss {
public void project(){
System.out.println("老板一个大饼我要做个新项目");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class DynamicProxy implements Bossinterface {

private Boss boss;

public DynamicProxy(){

}

public DynamicProxy(Boss boss) {
this.boss = boss;
}

@Override
public void project() {
System.out.println("项目经理给我想法子");
System.out.println("策划给我设计");
boss.project();
System.out.println("程序员给我写");
System.out.println("运维给我善后");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public class JdkDynamicProxy {

public static void main(String[] args) {

//该设置用于输出jdk动态代理产生的类
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");

Bossinterface proxy = (Bossinterface)Proxy.newProxyInstance(
Thread.currentThread().getContextClassLoader(),
new Class[]{Bossinterface.class},
new myInvocationHandler(new DynamicProxy(new Boss())));
proxy.project();
}

//自定义invocationHandler
public static class myInvocationHandler implements InvocationHandler{

private Bossinterface bossinterface;

public myInvocationHandler(Bossinterface bossinterface) {
this.bossinterface = bossinterface;
}

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

method.invoke(bossinterface);
return null;
}
}
}
cglib动态代理
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<dependencies>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>utf-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public static void main(String[] args) {
Enhancer enhancer=new Enhancer();
enhancer.setSuperclass(MaleSinger.class);
enhancer.setCallback(new MethodInterceptor() {
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("---------");
Object invoke = methodProxy.invokeSuper(o,objects);
System.out.println("++++++++++");
return invoke;
}
});
MaleSinger maleSinger = (MaleSinger)enhancer.create();
maleSinger.sing();
}

Java动态代理只能够对接口进行代理,不能对普通的类进行代理(因为所有生成的代理类的父类为Proxy,Java类继承机制不允许多重继承)

CGLIB能够代理普通类

Java动态代理使用Java原生的反射API进行操作,在生成类上比较高效;CGLIB使用ASM框架直接对字节码进行操作,在类的执行过程中比较高效

ASM动态代理的本质

ASM是一个java字节码操纵和分析框架,它可以直接以二进制的形式修改class或动态生成class

1
2
3
4
5
6
7
8
9
10
<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm-util</artifactId>
<version>8.0.1</version>
</dependency>
<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm</artifactId>
<version>8.0.1</version>
</dependency>

你知道的越多 你不知道的越多 嘿 我是小博 带你一起看我目之所及的世界……

-------------本文结束 感谢您的阅读-------------

本文标题:常用的设计模式

文章作者:小博

发布时间:2022年03月25日 - 14:51

最后更新:2022年10月26日 - 13:27

原始链接:https://codexiaobo.github.io/posts/4099381251/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。