最近一直在研究设计模式,主要以专研《Head First设计模式》以及看网上各路大神的见解。这边想用自己对于23种设计模式的理解,用一种非程序员都能理解的方式去介绍设计模式,毕竟我觉得设计模式是一种很好的处理问题的思想方法,不应该仅限于代码的实现。希望能够对于刚接触设计模式的小伙伴们有所帮助。当然有不对的地方,欢迎下方留言。一定及时修改。
让我们一起动动脑瓜子,逐步解决如下问题吧!
首先,我们先假设我们有三个不同类型的女朋友。
第一位:可爱小妹妹,喜欢用QQ跟你聊天。
第二位:同岁青梅竹马,喜欢用微信跟你聊天。
第三位:御姐上司,喜欢用钉钉跟你聊天。
然后,每天晚上呢,我们都会跟女朋友说晚安,并让她们早点休息。一开始我们还是能够应付的。不过慢慢的我们发现,不停地切换三个软件去聊天实在是麻烦。于是,我们就想了一个办法。
我们跟每个女朋友说,以后我们聊天都直接打电话吧。你们把电话号码给我。不然我们就分手!!!女朋友都觉得我们很好,不舍得分手就同意了我们的安排。(如果不同意,那就真分手了。不联系了哦!)
现在我们跟女朋友们都开始电话联系了。这里的实现有几个必要的条件:
第一:女生有手机,有手机号码。
第二:你有手机号码本,并且女朋友们把她们的手机号码告诉了你。
第三:女生承认是你的女朋友,愿意接你电话。
只有满足以上三者条件。我们才能方便的用打电话的方式,方便的联系每一个女朋友。
有了上面的条件,我们发现谈恋爱对我们来说,很是轻松啊。简简单单就应付了三个女朋友。这时新的目标出现了。我们发现住我们隔壁的邻居小妹很漂亮。并且偶尔一起上下楼,日久生情嘛。有一天小妹主动问我们,能不能跟我们处情侣关系。当然我们不是随便的人,我们可是有条件的。只有小妹能够接受三个要求,才能做我们女朋友。
三个条件跟对待其他女朋友一样:
第一:女生有手机,有手机号码。
第二:你有手机号码本,并且女朋友们把她们的手机号码告诉了你。
第三:女生承认是你的女朋友,愿意接你电话。
就这样我们的女朋友又多了一个。当然只要有缘分,女生只要愿意接受上面的条件,都能做我们女朋友。多多益善。
当然了随着女朋友越来越多,总有我们应付不过来的时候,两个人的感情就出现了问题,你决定跟某些女生分手不再联系。这时你从自己的号码本上删掉了某些女生的联系方式。也不会再去打电话给她们。
看完上面的例子,获取大家还有点小蒙,这恋爱之术跟我们大观察者设计模式有什么关系。别着急这就跟大伙解释。
首先,简单描述观察者模式:观察者模式定义的是对象之间一对多的依赖,当一个对象状态改变时,会通知所有的依赖者。
那么,在上述案例中,我们这个角色,就可以等价于观察者模式里的对象,也就是被观察者,我们的众多女朋友可以等价于观察者或依赖者。当我们有事的时候,都会通过统一的方式去通知所有的女朋友。在目前我的理解中,通知方式的统一是观察者模式的核心。后期有更深理解时,再回来修改。有什么高深间接欢迎下方留言。
接下来让我们用代码实现并详细了解一下观察者模式。
让我们回到最开始的阶段。
1、有三个女朋友,用三种方式跟我们联系。
新建三个类,代表女朋友:
public class GirFriend01 {
public void QQ(String thing){
System.out.println("我是一号,我现在去"+thing);
}
}
public class GirFriend02 {
public void WeChat(String thing){
System.out.println("我是二号,我现在去"+thing);
}
}
public class GirFriend03 {
public void DingDing(String thing){
System.out.println("我是三号,我现在去"+thing);
}
}
2、然后新建一个类,代表我们。我们可以让女朋友们去做相同的事情。君子有言:我对每个女朋友的爱都是全心全意的,没有差别。对吧!
public class Me {
GirFriend01 girFriend01 = new GirFriend01();
GirFriend02 girFriend02 = new GirFriend02();
GirFriend03 girFriend03 = new GirFriend03();
public void tellGirlsToDo(String thing){
girFriend01.QQ(thing);
girFriend02.WeChat(thing);
girFriend03.DingDing(thing);
}
}
3、写个简单的测试类,测试一下我们的代码:
public classTest {
public static void main(String[] args) {
Me me = new Me();
me.tellGirlsToDo("睡觉,晚安");
}
}
运行结果:
我是一号,我现在去睡觉,晚安
我是二号,我现在去睡觉,晚安
我是三号,我现在去睡觉,晚安
女朋友们都听到我们的问候,乖乖睡觉去了。没有问题。
4、但是从上诉代码中我们可以明细感觉到很多代码可以简化,(如果你有看我关于设计模式系列的第一篇策略模式的话,应该能这么认为。常人能看懂的设计模式(一)策略模式)
可封装的部分主要有两块:
第一点:我们应该有一个对象集合统一管理我们的女朋友。这样不管是新的女朋友的增加还是感情分裂的女朋友的删除都会更加方便。
第二点:跟每个女朋友的联系方式应该用同一种,不然太麻烦了。
根据上诉两点,我们对代码进行第一次优化:
a、作为我们的女朋友,要用我们定好的约定跟我们联系,也就是例子中的打电话。根据策略模式的基础,当我们创建特定类的时候目前有两种方式:一、继承一个父类。二、实现某个接口。我们更应该是秉承“有一个”比“是一个”好的方式。去实现一个接口。这里的话,当然是让女朋友们都实现打电话的接口。
定义打电话接口:
public interface Phone {
void phone();
}
更新女朋友的类
public class GirFriend01 implements Phone{
public void QQ(String thing){
System.out.println("我是一号,我现在去"+thing);
}
@Override
public void phone(String thing) {
System.out.println("我是一号,我现在去"+thing);
}
}
public class GirFriend02 implements Phone{
public void WeChat(String thing){
System.out.println("我是二号,我现在去"+thing);
}
@Override
public void phone(String thing) {
System.out.println("我是二号,我现在去"+thing);
}
}
public class GirFriend03 implements Phone{
public void DingDing(String thing){
System.out.println("我是三号,我现在去"+thing);
}
@Override
public void phone(String thing) {
System.out.println("我是三号,我现在去"+thing);
}
}
b、更新我们的类,用一个对象集合来管理我们的女朋友们。能够增加和删除女朋友。
public class Me {
private List grils = new ArrayList<>();
public void addGirls(Phone phone){
grils.add(phone);
};
public void delGirls(Phone phone){
grils.remove(phone);
}
public void tellGirlsToDo(String thing){
for(Phone phone:grils){
phone.phone(thing);
}
}
}
这块聪明的同志们肯定能想到,Me作为一个特定的类,我们应该也能对齐进行优化。
定义一个GetGirls接口。里面包含了我们Me里面实现的几个方法。这样我们就能创建不同的Me了。
定义GetGirls接口:
public interface GetGirls {
void addGirls(Phone phone);
void delGirls(Phone phone);
void tellGirlsToDo(String thing);
}
Me类实现GetGirls接口:
public class Me implements GetGirls{
private List grils = new ArrayList<>();
public void addGirls(Phone phone){
grils.add(phone);
};
public void delGirls(Phone phone){
grils.remove(phone);
}
public void tellGirlsToDo(String thing){
for(Phone phone:grils){
phone.phone(thing);
}
}
}
5、编写测试类查看测试结果
public class Test {
public static void main(String[] args) {
Me me = new Me();
me.addGirls(new GirFriend01());
me.addGirls(new GirFriend02());
me.addGirls(new GirFriend03());
me.tellGirlsToDo("睡觉,晚安!");
}
}
测试结果:
我是一号,我现在去睡觉,晚安!
我是二号,我现在去睡觉,晚安!
我是三号,我现在去睡觉,晚安!
到此为止其实。我们已经从无到有完成了观察者模式。 东西应该不是很难理解。主要还是把该封装的简化的地方进行了改善。当然,这边Java API有内置的观察者模式。java.util包中,包含有最基本的Observer接口与Observable类。这与我们上面例子里写的
GetGirls接口和Phone接口差不多。只是Observer接口与Observable类使用上更为方便。
很多功能前辈已经帮我们写好了。甚至我门可以用push和pull的方式来传递消息。
让我们用Observer接口与Observable类来实现我们的例子。
1、修改我们Phone接口名字为Observer,方法名改为update,其他不变。
public interface Observer {
void update(String thing);
}
2、修改我们的女朋友们。其实没什么改变就换下方法名
public class GirFriend01 implements Observer {
public void QQ(String thing){
System.out.println("我是一号,我现在去"+thing);
}
@Override
public void update(String thing) {
System.out.println("我是一号,我现在去"+thing);
}
}
public class GirFriend02 implements Observer {
public void WeChat(String thing){
System.out.println("我是二号,我现在去"+thing);
}
@Override
public void update(String thing) {
System.out.println("我是二号,我现在去"+thing);
}
}
public class GirFriend03 implements Observer {
public void DingDing(String thing){
System.out.println("我是三号,我现在去"+thing);
}
@Override
public void update(String thing) {
System.out.println("我是三号,我现在去"+thing);
}
}
3、现在我们要开始修改我们的Me类了。这块改动比较大,主要变化有下面几点:
a、Observable类是一个类,不是接口。我们是用继承的方式来创建Me类的。
b、多了一个setChange()方法,标记已经变化的事实。
c、去除了增加女朋友和删除女朋友以及联系女朋友的方法。已经从超类继承了这些行为。
。。。
兄弟们写不动了。关于官方的观察者模式具体使用可以参考其他文章。我这边就带大家理解理解。剩下的,我后面有时间补上吧。码字真的比敲代码还累。
欢迎一键三连哈。。。。