写在前面
设计模式之禅这本书也是博主看了几本设计模式的开头才决定以这本书作为学习设计模式的资料。像小傅哥的重学Java设计模式,好处是以真实的项目案例的逻辑来搭配设计模式中的各个模式来帮助你理解,真正的运用到项目生产中,但是其中只有核心逻辑被写出来,像博主这样的设计模式小白来说,还是有些难度的。而设计模式之禅这本书,以故事的形式带入,尤其体现了面向对象的思想,真正的创建对象帮你干活。
策略模式
这一章以诸葛亮赠送三条锦囊给赵云助刘备度过难关.诸君请跟着本文的视角看赵云是如何运用策略模式渡刘备
定义接口
定义一个策略接口,诸葛亮老人家给赵云的三个锦囊妙计的接口
public interface IStrategy {
//每个锦囊妙计都是一个可执行的算法
void operate();
}
接口我们都知道的,我们在接口里只写方法名,而谁实现了这个接口,根据实现类的功能来具体实现方法.
接口的实现类(妙计)
谁实现了接口谁重写
妙计一:开个后门撒
public class BackDoor implements IStrategy{
@Override
public void operate() {
System.out.println("找乔国老帮忙,让吴国太给孙权施加压力");
}
}
妙计二:给个绿色通道哈
public class GivenGreenLight implements IStrategy {
@Override
public void operate() {
System.out.println("求吴国太开个绿灯,放行");
}
}
妙计三:断后
public class BlockEnemy implements IStrategy {
@Override
public void operate() {
System.out.println("孙夫人断后,挡住追兵");
}
}
锦囊
public class Context {
private IStrategy strategy;
public Context(IStrategy strategy) {
this.strategy = strategy;
}
//使用计谋
public void operate(){
this.strategy.operate();
}
}
这里可要好好唠一唠了,根据Java核心卷一中所阐述
接口不是类。具体的说,不能使用new运算符实例化一个接口:即
x = new Interface(...) //ERROR
不过,尽管不能构造接口的对象,却能声明接口的变量:
Interface x; //OK
接口变量必须引用了实现了这个接口的类对象:
x = new Object(...) //OK provided Object implements Interface
在锦囊里就是这样使用,我们创造一个接口变量,没有使用new,因为博主也有点忘记了,因为博主记得的是接口无法被实例化,第一眼看到还以为是接口被实例化了,吓得博主赶忙看了一眼书。还好还好,本命知识没记错。
尤其在构造器里体现了,构造器需要传入的类型需要的是接口的类型(接口的实例),在下面我会在解释这一段。
而锦囊里的Operate()方法,使用this.strategy.operate(),这个意思是本类的接口变量调用了接口内的operate方法
赵云使妙计救主
public class ZhaoYun {
//赵云出场了,他根据诸葛的交代,一次拆开妙计
public static void main(String[] args) {
Context context;
System.out.println("--------刚刚到吴国的时候拆第一个--------");
context = new Context(new BackDoor());//拿到妙计
context.operate();//拆开执行
System.out.println("\n\n\n");
System.out.println("--------刘备乐不思蜀了,拆开第二个了--------");
context = new Context(new GivenGreenLight());
context.operate();//执行了第二个锦囊了
System.out.println("\n\n\n");
System.out.println("--------孙权的小兵追了,咋办?拆第三个--------");
context = new Context(new BlockEnemy());
context.operate();//孙夫人退兵
System.out.println("\n\n\n");
}
}
我们拿赵云使用一个锦囊为例,我们可以看到,在主方法中创建了一个context变量,这个变量实例化一个对象后,构造器传入的是一个实现了接口的妙计类,这跟我们在上面提到的
并且,当context执行operate方法时我们debug查看一下
这里的方法其实是真正的接口实现类的方法也就是BackDoor这个类来实现
最后也是走到了BackDoor类里
小总结
- 问题来了:赵云实际不知道是那个策略呀,他只知道拆第一个锦囊,
- 而不知道是BackDoor:这个妙计,咋办?似乎这个策略模式已经把计谋名称写出来了
- 错!BackDoor、GivenGreenLight、BlockEnemy.只是一个代码,你写成first、second、third,没人会说你错!
- 策略模式的好处就是:体现了高内聚低耦合的特性呀,缺点嘛,这个那个,我回去再查查
什么是高内聚低耦合?
广义上的讲
高内聚低耦合,是软件工程中的概念,是判断软件设计好坏的标准,主要用于程序的面向对象的设计,主要看类的内聚性是否高,耦合度是否低。目的是使程序模块的可重用性、移植性大大增强。通常程序结构中各模块的内聚程度越高,模块间的耦合程度就越低。内聚是从功能角度来度量模块内的联系,一个好的内聚模块应当恰好做一件事,它描述的是模块内的功能联系;耦合是软件结构中各模块之间相互连接的一种度量,耦合强弱取决于模块间接口的复杂程度、进入或访问一个模块的点以及通过接口的数据。
低耦合
耦合就是元素与元素之间的连接,感知和依赖量度。这里说的元素即是功能,对象,系统,子系统。模块。
例如:现在有方法A和方法B
我们在A元素去调用B元素,当B元素有问题或者不存在的时候,A元素就不能正常的工作,那么就说元素A和元素B耦合。
耦合带来的问题
当元素B变更或者不存在时,都将影响元素A的正常运作,影响系统的可维护性和易变更性。同时元素A只能运行在元素B中,这也大大的降低了A元素的可复用性。
低耦合如何去做
- A不能过度依赖B
- 模块的功能划分尽可能的单一, 遵循单一职责原则
- 要多使用接口而不是继承:我们不难发现。继承就是一种耦合,假如子类A继承了父类B,不论是直接继承或者间接继承,一但父类B不存在或者发生任何变更,都将导致子类A不得不修改或者重写。假如父类B的子类数十上百的,这就是灾难性的变更。
- 能用 private 的地方,坚决不用 public, 不要给类的任何属性都加 set 方法,体现良好的封装性,暴露越少,影响也就越少。 这里我就想到了最常用的一个注解Lombok,他的一个主机就是把类里全部的属性都生成get/set方法,而哪吒有一篇文章里讲的就是lombok注解的弊端(为什么人们宁可用Lombok,也不把成员设为public?_哪 吒的博客-CSDN博客),感兴趣的小伙伴可以去看一看,写的很不错
高内聚
高内聚是另外一个评判软件设计质量的标准。内聚更为专业的说法叫做功能内聚,是对系统中元素职责的相关性和集中度的量度。如果元素有高度的相关职责,除了这些职责在没有其他的工作,那么该元素就有高内聚。
例如:
就好像,如果我是一个项目经理,我的职责是监控和协调我的项目各个阶段的工作。当我的项目进入需求分析阶段,我会让需求分析员来完成;当我的项目进入开发阶段,我会让软件开发人员来完成;当我的项目需要测试的时候,我会请求测试人员。如果我参与了开发,我就不是一个高内聚的元素,因为开发不是我的职责。
通过这一篇文章,我相信小伙伴会对策略模式有一个初步的概念了,这就要求我们在写代码的时候要多使用接口去实现,而少有继承,如果你学到框架的话,会发现我们其实也很少单一使用继承的关系,都是通过单继承多实现来减少耦合度的。小生不才,对于设计模式也是浅谈感受,如有什么说错的地方还请大家帮忙指正,海涵海涵。
标签:operate,之禅,--,元素,接口,内聚,new,设计模式,public From: https://blog.51cto.com/u_15915681/6101508