目录
1,什么是观察者,外观模式?
在了解这两个模式的代码及意义之前我们先了解下这两个设计模式到底是怎么样的
观察者模式:
观察者模式是一种行为设计模式,它允许对象之间的一对多依赖关系,当一个对象的状态发生变化时,所有依赖于它的对象都会收到通知并自动更新。
外观模式:
外观模式(Facade Pattern)是一种设计模式,它提供了一个简化接口,用于访问复杂子系统的功能。它隐藏了子系统的复杂性,并提供了一个统一的接口,使得客户端更容易使用。
2,观察者模式:
还是跟之前一样在了解观察者模式代码之前,继续让我们设想一个场景 :假如你现在急用钱,然后借了凡哥,签哥,马大师的钱,但是为了免得麻烦他们天天要钱,你跟他们说,等我有钱了微信通知你们,到时候你们再来找我要钱。那么让我们来看看装饰器到底是怎么实现的吧。
BorrowPerson(借钱人接口):
//借钱接口(本人)
public interface BorrowPerson {
//借钱方法,找人借钱,传入参数为债主信息(pay)
void borrowMoney(Pay pay);
//传入状态(1有钱, 2没钱), 微信通知别人我要还钱了。
void weChat(Integer status);
}
接下来我们定义个类You,实现借钱人接口。
You(你本人):
//借钱人你自己,实现借钱接口
public class You implements BorrowPerson {
//债主集合, 里面装的全是我的债主(哈哈)
private List <Pay> pays = new ArrayList<>();
//重写借钱方法
@Override
public void borrowMoney(Pay pay) {
//添加债主信息
pays.add(pay);
}
//重写还钱方法,传入状态(1有钱, 2没钱)
@Override
public void weChat(Integer status) {
if (status == 1){
//有钱了循环所有债主信息,通知他们来拿钱。
pays.forEach(p -> {
//要钱方法
p.takeMoney();
});
}else {
System.out.println("现在的我没钱");
}
}
}
现在类图如下:
那么接下来,让我们定义一个债主接口:
Pay(债主接口):
//付钱接口, 借给我钱的人(债主)
public interface Pay {
//要钱方法, 等我有钱了通知你们,你们再来找我要钱
void takeMoney();
}
定义完债主接口,再来写几个债主类实现这个接口吧。
CaiXuKu(坤债主):
//债主蔡旭坤, 实现债主接口
public class CaiXuKun implements Pay{
//重写要钱方法
@Override
public void takeMoney() {
System.out.println("坤哥来要钱了");
}
}
MaBaoGuo(马债主):
//债主马报国, 实现债主接口
public class MaBaoGuo implements Pay{
//重写要钱方法
@Override
public void takeMoney() {
System.out.println("马大师来要钱了");
}
}
WuYiFan(乌债主):
//债主乌一凡, 实现债主接口
public class WuYiFan implements Pay{
//重写要钱方法
@Override
public void takeMoney() {
System.out.println("签哥来要钱了");
}
}
现在我们的类图如下:
Main(主函数):
//主函数
public class Main {
public static void main(String[] args) {
//创建借钱人, 你自己
BorrowPerson you = new You();
//找坤哥借钱
you.borrowMoney(new CaiXuKun());
//找马大师借钱
you.borrowMoney(new MaBaoGuo());
//找签哥借钱
you.borrowMoney(new WuYiFan());
//有钱了,用微信通知他们
you.weChat(1);
}
}
⚪运行结果:
坤哥来要钱了
马大师来要钱了
签哥来要钱了
3,观察者模式的优缺点:
观察者模式的优点包括:
- 松耦合:观察者模式通过抽象耦合了观察者(债主)和被观察者(借钱人)之间的关系,使它们可以独立地变化。被观察者(借钱人)只需要知道观察者(债主)接口,而不需要了解具体的观察者实现。
- 可扩展性:新的观察者(债主)可以很容易地添加到系统中,无需修改现有代码。被观察者(借钱人)和观察者(债主)之间的关系可以动态地建立和解除。
- 通知机制:观察者模式提供了一种简单的通知机制,当被观察者的状态发生变化时,会自动通知所有的观察者。这使得观察者可以及时获取到最新的状态信息。
观察者模式的缺点包括:
- 通知顺序问题:观察者模式中观察者的调用顺序是不确定的,如果观察者之间有依赖关系,可能导致意外的结果。
- 内存泄漏:如果观察者没有正确地解注册,可能会导致内存泄漏问题。被观察者在通知观察者时需要确保观察者已经被正确地解注册。
- 更新频繁:如果被观察者的状态更新频繁,会导致观察者接收到大量的通知,可能影响系统的性能。
4,外观模式:
同样的,在了解外观模式之前我们也设想一个场景:假如你现在饿了想吃饭,但是吃饭呢你得买菜,洗菜,做菜,很麻烦,为了方便你选择直接叫个厨师来,让他来帮你买菜,洗菜,做菜,你要做的就是等待厨师吧饭弄好直接吃就行了。可能思想高的同学到这里大致都能猜出整个代码怎么实现的了,让我们来看看吧。
Buy(买菜类):
//买菜方法
public class Buy {
void Buying(){
System.out.println("厨师正在买菜");
}
}
Wash(洗菜类):
//洗菜方法
public class Wash {
void Washing(){
System.out.println("厨师正在洗菜");
}
}
Do(做菜类):
//做菜方法
public class Do {
void Doing(){
System.out.println("厨师正在做菜");
}
}
在定义完这三个类,写完他们相应的方法后,我们紧接着创建一个厨师类,来一个个创建这些类调用这些方法吧。
Chef(厨师类):
//厨师方法
public class Chef {
//厨师方法
String Chafing(){
//买菜类
Buy buy = new Buy();
//洗菜类
Wash wash = new Wash();
//做菜类
Do d = new Do();
buy.Buying();
wash.Washing();;
d.Doing();
return "厨师吧做好的菜端上来了";
}
}
现在我们的类图如下:
Main(主函数):
//主函数
public class Main {
public static void main(String[] args) {
//调用厨师方法
System.out.println(new Chef().Chafing());
System.out.println("我正在吃饭");
}
}
⚪运行结果:
厨师正在买菜
厨师正在洗菜
厨师正在做菜
厨师吧做好的菜端上来了
我正在吃饭
5,外观模式的优缺点:
外观模式的优点包括:
- 简化客户端使用:外观模式提供了一个简单的接口,隐藏了底层子系统的复杂性。客户端不需要了解子系统的内部工作原理,只需要调用外观接口即可完成操作。
- 解耦合:外观模式将客户端与子系统之间进行解耦,通过外观类作为中间层,客户端与子系统之间不直接交互。这样可以提高系统的灵活性和可维护性。
- 提高代码复用性:外观模式将子系统的功能封装在一个外观类中,可以在多个地方重复使用这个外观类,避免了代码的重复编写。
外观模式的缺点包括:
- 不符合开闭原则:如果需要新增或修改子系统的功能,可能需要修改外观类的代码。这违反了开闭原则,可能会影响到其他使用该外观类的客户端。
- 可能引入不必要的依赖:外观模式将子系统封装在一个外观类中,客户端只能通过外观类来访问子系统,这可能导致客户端与外观类之间的依赖增加。
总的来说,外观模式在简化客户端使用、解耦合和提高代码复用性方面具有优点,但也需要注意不符合开闭原则和可能引入不必要的依赖的缺点。在实际应用中,
6,总结:
以我个人来讲,多看设计模式,提升最大的是你的思想,就像我们抄别人代码,难道真正重要的是代码吗?并不是而是别人的思想,当你看过更多的设计模式后,你可能仅仅看到这个设计模式的概念的时候,你的大脑里就能构思出大概的代码应该是怎么实现的,这就是你思想的提升,可能在最开始的时候你学什么设计模式都觉得,哇这个人思维巨厉害巨高,但是当你已经看过并且理解部分设计模式的时候,你可能就会发现这个时候的自己只看概念也能理解的七七八八了。