我是靠谱客的博主 醉熏芒果,这篇文章主要介绍Java你熟悉的设计模式,现在分享给大家,希望可以做个参考。

1、说一下你熟悉的设计模式?

单例模式

简单点说,就是一个应用程序中,某个类的实例对象只有一个,你没有办法去new,因为构造器是被private修饰的,一般通过getInstance()的方法来获取他们的实例。

getInstance()的返回值是一个对象的引用,并不是一个新的实例,所以不要错误的理解成多个对象。单例模式实现起来很容易,直接看demo:

懒汉式(线程不安全)

复制代码
1
2
3
4
5
6
7
8
9
10
11
public class Singleton{ private static Singleton singleton; private Singleton(){} public static Singleton getInstance(){ if(singleton == null){ singleton == new Singleton(); } return singleton;1 } }

懒汉式(线程安全)

复制代码
1
2
3
4
5
6
7
8
9
10
11
public class Singleton{ private static Singleton singleton; private Singleton(){} public static Synchronized Singleton getInstance(){ if(intance == null){ instance == new Singleton(); } return instance; } }

饿汉式写法(☆)

复制代码
1
2
3
4
5
6
7
8
public class Singleton{ private static Singleton instance = new Singleton(); privaet Singleton(){} public static Singleton getInstace(){ return instance; } }

静态内部类(☆)

复制代码
1
2
3
4
5
6
7
8
9
10
public class Singleton{ private static class SingletonHolder{ private static final Singleton INSTANCE = new Singleton(); } private Singleton(){} public static final Singleton getInstance(){ return SingletonHolder.INSTANCE; } }

枚举

复制代码
1
2
3
4
5
public enum Singleton{ INSTANCE; public void whateverMethod(){} }

这种方式是Effective Java作者Josh Bloch提倡的方式,它不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象。可谓是很坚强的壁垒啊,不过,个人认为由于1.5中才加入enum特性,用这种方式写不免让人感觉生疏。

双重校验锁

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Singleton{ private volatile static Singleton singleton; private Singleton(){} public static Singleton getSingleton(){ if(singleton == null){ synchronized(Singleton.class){ if(singleton == null){ singleton = new Singleton(); } } } return singleton; } }

总结:我我个人比较喜欢静态内部类写法和饿汉式写法,其实这两种写法能够应付绝大多数情况了。其他写法也可以选择,主要还是看业务需求吧。

观察者模式

​ 对象间一对多的依赖关系,当一个对象的状态发生改变时,所依赖于它的对象都得到通知并被自动更新。

img

​ 观察者模式UML图

看不懂图的人端着小板凳到这里来,给你举个栗子:假设有三个人,小美(女,22),小王和小李。小美很漂亮,小王和小李是两个程序猿,时刻关注着小美的一举一动。有一天,小美说了一句:“谁来陪我打游戏啊。”这句话被小王和小李听到了,结果乐坏了,蹭蹭蹭,没一会儿,小王就冲到小美家门口了,在这里,小美是被观察者,小王和小李是观察者,被观察者发出一条信息,然后观察者们进行相应的处理,看代码:

复制代码
1
2
3
4
5
public interface Person{ //小王和小李通过这个接口可以接收到小美发过来的消息 void getMessage(String s); }

这个接口相当于小王和小李的电话号码,小美发送通知的时候就会拨打getMessage这个电话,拨打电话就是调用接口,看不懂没关系,先往下看:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class LaoWang implements Person{ private String name = "小王"; public LaoWang(){} @Override public void getMessage(String s){ System.out.println(name + "接到了小美打过来的电话,电话内容是:" + s); } } public class LaoLi implements Person{ private String name = "小王"; public LaoLi(){} @Override public void getMessage(String s){ System.out.println(name + "接到了小美打过来的电话,电话内容是:->" + s); } }

代码很简单,我们再看看小美的代码:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class XiaoMei{ List<Person> list = new ArrayList<Person>(); public XiaoMei(){} public void addPerson(Person person){ list.add(person); } //遍历list,把自己的通知发送给所有暗恋自己的人 public void notifyPerson(){ for(Person person:list){ person.getMessage("你们过来吧,谁先过来谁就能陪我一起玩游戏!")} } }

测试类:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
public class Test{ public static void main(String[] args){ XiaoMei xiao_mei = new XiaoMei(); LaoWang lao_wang = new LaoWang(); LaoLi lao_li = new LaoLi(); //小王和小李在小美哪里都注册了一下 xiao_mei.addPerson(lao_wagn); xiao_mei.addPerson(lao_li); //小美向小王和小李发送通知 xiao_mei.notifyPerson(); } }

~~


装饰着模式

​ 对已有的业务逻辑进一步封装,使其增加额外的功能,如Java中的IO流就是使用了装饰者模式,用户在使用的时候,可以任意组装,达到自己想要的效果。举个例子,我想吃三明治,首先我需要一更大大的香肠,我喜欢吃奶油,在香肠上面加一点奶油,再放点蔬菜,最后再用两片面包夹一下,很丰盛的一顿午饭,营养又健康。那我们应该怎么来写代码呢? 首先,我们需要写一个Food类,让其他所有食物都来继承这个类,看代码:

复制代码
1
2
3
4
5
6
7
8
9
10
11
public class Food{ private String food_name; public Food(){} public Food(String food_name){ this.food_name = food_name; } public String make(){ return food_name; } }

然后我们写几个子类继承它:

复制代码
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 Bread extends Food{ private Food basic_food; public Bread(Food basic_food){ this.basic_food = basic_food; } public String make(){ return basic_food.make()+"+面包"; } } //奶油类 public class Cream extends Food{ private Food basic_food; public Cream(Food basic_food){ this.basic_food = basic_food; } public String make(){ return basic_food.make()+"+奶油"; } } //蔬菜类 public class Vegetable extends Food{ private Food basic_food; public Vegetable(Food basic_food){ this.basic_food = basic_food; } public String make(){ return basic_food.make()+"+蔬菜"; } }

这几个类都是差不多的,构造方法传入一个Food类型的参数,然后在make方法中加入一些自己的逻辑,如果你还是看不懂为什么这么写,不急,你看看我的Test类是怎么写的,一看你就明白了

复制代码
1
2
3
4
5
6
7
public class Test{ public static void main(String[] args){ Food food = new Brand(new Vegetable(new Cream(new Food("香肠")))); System.out.println(food.make()); } }

看到没有,一层一层封装,我们从里往外看:最里面我new了一个香肠,在香肠的外面我包裹了一层奶油,在奶油的外面我又加了一层蔬菜,最外面我放的是面包,是不是很形象,哈哈~ 这个设计模式简直跟现实生活中一摸一样,看懂了吗? 我们看看运行结果吧

img

​ 运行结果

一个三明治就做好了~


适配器模式

​ 将两种完全不同的事物联系到一起,就像现实生活中的变压器。假设一个手机充电需要的电压是20V,但是正常的电压是220V,这样,变压器就将20V的电压和手机联系体来了。

复制代码
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
public class Test{ public static void main(String[] args){ Phone phone = new Phone(); VoltageAdapter adapter = new ValtageAdapter(); phone.setAdapter(adapter); phone.charge(); } } //手机类 class Phone{ public static final int V = 220;//正常电压220V,是个常量 private VoltageAdapter adapter; //充电 public void charge(){ adapter.changeVoltage(); } public void setAdapter(VoltageAdapter adapter){ this.adapter = adapter; } } //变压器 class VoltageAdapter { //改变电压的功能 public void changeVoltage(){ System.out.println("正在充电。。。"); System.out.println("原始电压:"+Phone.v+"V"); System.out.println("经过变压器转换之后的电压:"+(Phone.v-200)+"V"); } }

img


工厂模式

​ 简单工厂模式:一个抽象的接口,多个抽象接口的实现类,一个工厂类,用来实例化抽象的接口

复制代码
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
//抽象产品类 abstract class Car { public void run(); public void stop(); } //具体实现类 class Benz implements Car { public void run() { System.out.println("Benz开始启动了。。。。")} public void stop() { System.out.println("Benz停车了。。。。")} } class Ford implements Car { public void run() { System.out.println("Ford开始启动了。。。。")} public void stop() { System.out.println("Ford停车了。。。。")} } //工厂类 class Factory { public static Car getCarInstance(String type) { Car c = null; if("Benz".equals(type)) { c = new Benz(); } if("Fork".equals(type)) { c = new Fork(); } return c; } } //测试类 public class Test { public static void main(String[] args) { Car c = Factory.getCarInstance("Beaz"); if(c!=null){ c.run(); c.stop(); }else { 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
32
33
34
35
36
//抽象产品角色 public interface Moveable { void run(); } //具体产品角色 public class Plane implements Moveable { @Override public void run() { System.out.println("plane...."); } } public class Broom implements Moveable { @Override public void run() { System.out.println("broom...."); } } //抽象工厂 public abstract class VehicleFactory { abstract Meveable create(); } //具体工厂 public class BroomFactory extends VehicleFactory { public Moveable create() { return new Broom(); } } //测试类 public class Test { public static void main(String[] args){ VehicleFactory factory = new BroomFactory(); Moveable m = factory.create(); m.run(); } }

​ 抽象工厂模式:与工厂方法模式不同的是,工厂方法模式中的工厂只生产单一的产品,而抽象工厂模式中的工厂生产多个产品。

复制代码
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
//抽象工厂类 public abstract class AbstractFactory { public abstract Vehicle createVehicle(); public abstract Weapon createWeapon(); public abstract Food createFood(); } //具体工厂类,其中Food,Vehicle,Weapon是抽象类 public class DefaultFactory extends AbstractFactory { @Override public Food createFood() { return new Apple(); } @Override public Vehicle createVehicle() { return new Car(); } @Override public Weapon createWeapon() { return new AK47(); } } //测试类 public class Test { public static void main(String[] args) { AbstractFactory f = new DefaultFactory(); Vehicle v = f.createVehicle(); v.run(); Weapon w = f.createWeapon(); w.shoot(); Food a = f.createFood(); a.printName(); } }

代理模式(proxy)

​ 有两种,静态代理和动态代理。举个静态代理例子:

到了一定的年龄,我们就要结婚,结婚是一件很麻烦的事情,(包括那些被父母催婚的)。有钱的家庭可能会找司仪来主持婚礼,显得热闹,洋气~好了,现在婚庆公司的生意来了,我们只需要给钱,婚庆公司就会帮我们安排一整套结婚的流程。整个流程大概是这样的:家里人催婚->男女双方家庭商定结婚的黄道即日->找一家靠谱的婚庆公司->在约定的时间举行结婚仪式->结婚完毕;婚庆公司打算怎么安排婚礼的节目,在婚礼完毕以后婚庆公司会做什么,我们一概不知。。。别担心,不是黑中介,我们只要把钱给人家,人家会把事情给我们做好。所以,这里的婚庆公司相当于代理角色

复制代码
1
2
3
4
5
6
//代理接口 public interface ProxyInterface { //需要代理的是结婚这件事 void marry(); }

婚庆公司的代码:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class WeddingCompany implements ProxyInterface { private ProxyInterface proxyInterface; public WeddingCompany(ProxyInterface proxyInterface) { this.proxyInterface = proxyInterface; } } @Override public void marry() { System.out.println("我们是婚庆公司的"); System.out.println("我们在做结婚前的准备工作"); System.out.println("节目彩排。。。"); System.out.println("礼物购买。。。"); System.out.println("工作人员分工。。。"); System.out.println("可以开始结婚了。。。"); proxyInterface.marry(); System.out.println("结婚完毕,我们需要做后续处理,你们可以回家了,其余的事情我们公司来做。"); }

婚庆公司需要做的事情很多,我们再看看结婚家庭的代码:

复制代码
1
2
3
4
5
6
7
public class NormalHome implements ProxyInterface { @Override public void marry() { System.out.println("我们结婚啦~"); } }

这个已经很明显了,结婚家庭只需要结婚,而婚庆公司要包揽一切,前前后后的事情都是婚庆公司来做,听说现在婚庆公司很赚钱的,这就是原因,干的活多,能不赚钱吗?

来看看测试代码:

复制代码
1
2
3
4
5
6
7
public class Test { public static void main(String[] args){ ProxyInterface proxyInterface = new WeddingCompany(new NormalHome()); proxyInterface.marry(); } }

运行结果如下:

img

动态代理先不说,跟java反射有关,后续再做总结:~~

最后

以上就是醉熏芒果最近收集整理的关于Java你熟悉的设计模式的全部内容,更多相关Java你熟悉内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(52)

评论列表共有 0 条评论

立即
投稿
返回
顶部