前言:设计模式的概念是很抽象的,不好理解,我第一次看完这些概念也是一面懵逼,又想了想,还是一面懵逼的。在这里将概念放在前面看不懂没关系,本章的正确学习方式应该是先看《案例演示》和《代码实现》然后再回头看概念(别看概念很难理解,其实都是纸老虎,将demo敲一遍,不懂,拿刀来砍我)
前言 :虽然有六大设计原则,二十三种设计模式,不过常见的设计模式也就那么几种,想要真正的掌握,肯定还需要我们结合具体的应用场景去练习去理解,方可应用!
一、装饰设计模式
-
什么是装饰设计模式?
- 当想要对已有的对象进行功能增强时,可以定义类,将已有对象传入,基于已有的功能,并提供加强功能。那么自定义的该类称为装饰类。这种模式就称之为装饰设计模式。
-
装饰设计模式的优点
- 装饰模式比继承要灵活。避免了继承体系臃肿。而且降低了类于类之间的关系。
-
Java IO流中大部分API就是通过装饰设计模式设计的
- 例如BufferReader
-
案例演示
- 路人甲,一个计算机专业毕业的学生,毕业以后想找高薪水的工作。假如此时这个路人甲只会Java和 JavaWeb,无奈技术不行,于是就想去某某IT培训机构,培训一下。经过艰苦的几个月培训,路人甲终于被放出来了。路人甲抬头看了看天空,阳光有点刺眼,但是此时的路人甲已经今非昔比了,,,
-
设计思路
- 装饰类通常会通过构造方法接收被装饰的对象,并基于被装饰的对象的功能,提供更强的功能。
-
代码实现(放心是完整)
/**
* Project:HelloWorld
* Package:cn.edu.java
* Author:SKFsky
* CreateTime:2017/12/13 14:11
* Description: 装饰设计模式
*/
public class Demo_Decorator {
public static void main(String[] args) {
//大学毕业时的路人甲
System.out.println("大学毕业时的路人甲:");
LuRenJia luRenJia = new LuRenJia();
luRenJia.code();
System.out.println();
//经过特训后的路人甲
System.out.println("经过特训后的路人甲:");
Trainning train = new Trainning(new LuRenJia());
train.code();
}
}
interface Coder {
public void code();
}
class LuRenJia implements Coder{
@Override
public void code() {
System.out.println("我会Java");
System.out.println("我会JavaWeb");
}
}
class Trainning implements Coder {
private LuRenJia lurenjia; //获取到被包装的类的引用
public Trainning(LuRenJia lurenjia){ //通过构造函数创建对象的时候,传入被包装的对象
this.lurenjia = lurenjia;
}
@Override
public void code() { //对其原有功能进行升级
lurenjia.code();
System.out.println("我学会了数据库");
System.out.println("我学会了Kotlin");
System.out.println("我学会了设计模式");
System.out.println("我学会了一阳指");
System.out.println("我学会了一目千行");
System.out.println("我学会了做笔记");
System.out.println("我学会了.....");
}
}
-
结果展示
我是大侠路人甲 -
再举一个例子
- 比如人吃饭,路人乙刚毕业的时候是一个穷大学生,因为穷,每天中午只能吃两个大馍(只能吃两个哦,吃多了,你还是好好想想晚上怎么办吧),路人乙每天也没有别的想法,简简单单的吃馍。可是有一天路人乙通过,,,,,有钱了,那么路人乙每天中午不仅可以吃烤鸡、烤鸭、烤炉猪,还可以吃兰州拉面了。原来只是简单的吃饭,通过,,,,,以后就可以不简单的吃饭了。通过了什么,当然是一个装饰者(中彩票)。自己实现去吧。
- 分享一则最近看到中彩票的一个笑话:Adode公司发布了一个问卷调查假如彩票中500万你会怎么用?(另外上海局部房价突破每平方米34万元,当然这和我们的故事没有关系,哈哈)。路人乙中了500万彩票。以前,中了500万彩票,当然是先买一个房子啦,然后再买一个车子,最后剩下的钱就去旅行。现在,中了500万彩票,当然也是先买一个房子啦,剩下的钱,当然是慢慢换房贷!
二、适配器设计模式
-
什么是适配器?
- 在使用监听器的时候, 需要定义一个类事件监听器接口.
- 通常接口中有多个方法, 而程序中不一定所有的都用到, 但又必须重写, 这很繁琐.
- 适配器简化了这些操作, 我们定义监听器时只要继承适配器, 然后重写需要的方法即可.
-
b.适配器原理
- 适配器就是一个类, 实现了监听器接口, 所有抽象方法都重写了, 但是方法全是空的.
- 适配器类需要定义成抽象的,因为创建该类对象,调用空方法是没有意义的.
- 目的就是为了简化程序员的操作, 定义监听器时继承适配器, 只重写需要的方法就可以了.
-
案例演示
- 我们知道一般的和尚每天都需要打坐,念经,习武,但是每个和尚的性格都不一样,不可能所有的和尚都是千篇一律的,就像唐僧和鲁智深,就是完全不同的两个和尚。每个和尚都是独立的,我们也不能要求每个和尚都是一模一样的,所以我们需要有一个中间类,让每个人有自己的个性。
-
设计思路
- 定义一个接口
- 定义一个抽象类实现所有的接口
- 别的类继承这个抽象类即可,我们管这个抽象类的名字叫适配器
-
代码实现
/**
* Project:HelloWorld
* Package:cn.edu.java
* Author:SKFsky
* CreateTime:2017/12/13 15:10
* Description: 适配器设计模式
*/
public class Demo_Adapter {
public static void main(String[] args) {
tangtang tang = new tangtang();
tang.dazuo();
tang.nijing();
luzhishen lu = new luzhishen();
lu.xiwu();
lu.chirou();
lu.dajia();
}
}
//和尚接口
interface HeShang{
public void nijing();//念经
public void dazuo();//打坐
public void paobu();//跑步
public void xiwu();//习武
}
//适配器,实现了接口,并且定义成抽象类型的类了(抽象的类不能被实例化),这里面的方法都是空的,不需要去实现
abstract class Adapter implements HeShang{
@Override
public void nijing() {
}
@Override
public void dazuo() {
}
@Override
public void paobu() {
}
@Override
public void xiwu() {
}
}
//唐僧
class tangtang extends Adapter {
@Override
public void nijing() {
System.out.println("我是唐僧我喜欢念经");
}
@Override
public void dazuo() {
System.out.println("我是唐僧我喜欢打坐");
}
}
//鲁智深,我们的知道他是一个花和尚,喜欢习武,吃酒吃肉
class luzhishen extends Adapter {
@Override
public void xiwu() {
System.out.println("我是鲁智深我喜欢习武");
}
public void chirou() {
System.out.println("我是鲁智深我喜欢吃肉");
}
public void dajia() {
System.out.println("我是鲁智深我喜欢打架");
}
}
-
结果展示
东游记 - 总结
- 这样继承自适配器的类,可以实现父类方法,同时也可以有自己扩展的方法。
三、模板方法设计模式
-
什么是模板方法设计模式?
- 模版方法模式就是定义一个算法的骨架,而将具体的算法延迟到子类中来实现
-
优点
- 使用模版方法模式,在定义算法骨架的同时,可以很灵活的实现具体的算法,满足用户灵活多变的需求
-
缺点
- 如果算法骨架有修改的话,则需要修改抽象类
-
案例演示
- 设计一个模板,用了计算我们执行某一个方法所要的时间
-
设计思路
- Java是面向对象的编程,定义一个类,实现模板的方法
- 子类继承这个类实现相关的方法
-
代码实现
/**
* Project:HelloWorld
* Package:cn.edu.java
* Author:SKFsky
* CreateTime:2017/12/13 15:42
* Description: 模板方法设计模式
*/
public class Demo_Template {
public static void main(String[] args) {
Demo demo = new Demo();
long time = demo.getTime();
System.out.println(time);
}
}
//定义成抽象类,因为定义了一个抽象方法code()
abstract class GetTime {
//用final关键字修饰,因为该方法是一个模板,不希望让子类重写。但是可以被子类调用。计算code方法的执行时长
public final long getTime() {
long start = System.currentTimeMillis();
code();
long end = System.currentTimeMillis();
return end - start;
}
//定义成抽象的,在子类中去实现
public abstract void code();
}
class Demo extends GetTime{
@Override
public void code() {
int i = 0;
while (i<100000) {
System.out.println("x");
i++;
}
}
}
-
结果展示
毫秒
网友评论