从多态思想,抽象工厂模式,代理模式谈谈"接口"是如何帮住我们松耦合的
前言:
为了讲清楚接口松耦合的原理,我设计了一种接口松耦合设计模式,用到了面向对象思想,也用到了不被固定场景限制的动态反射思想,标题里的三种模式是我认为最能讲解清楚接口松耦合设计模式的思想.
概述:
java通过接口松耦合,实现了抽象父类的具体功能类的多态化,那么,两个用实现了统一接口的抽象类的具体类是怎么耦合的呢?
我们以Thread thread = new JumpThread(new BoyJump())为例,还原泰坦尼克号Jack跳船的场景.
将BoyJump类里的run()方法做线程体,通过代理设计模式被JumpThread类里的空白run()方法使用(PS:一个线程类的run()方法就是该线程的入口,作用类似main()方法).BoyJump是Jump的子类,JumpThread是Thread的子类.这两个父类都implements了Runable接口.
写这两个子类还有个好处,通过子类名他人一看就知道这个类是用在什么场景的,满足代码命名自证其义的设计思想.不致于其他人阅读我的代码时一脸懵逼,猜不透Thread和Jump是用在什么场景下的.
设计详情
Jump类里写好接口方法(将其改造成能用上这种接口),在jumpThread具体线程类里通过构造方法接收boyJump类的对象,并让本类里的空白方法使用boyJump类继承自Jump类的run方法,从而实现接口模式.这种设计模式的好处与应用法我会在结尾给大家做个总结.
代码演示
我们共计需要在工程内写一个接口,两个抽象实现类,两个具体继承类
- 接口
/**
*设计一个抽象接口,用于定义比Abstract还Abstract的功能方法
*相当于定义了一个手机充电线插头的形状,是micro-C还是type-C,手机才能设计对应的被插的凹槽.
*/
public interface Runable{
public void run();
}
- Thread类实现该接口
/**
*传统的线程设计方法因为implements了Runable接口,要重写run方法.但是这样一来这个线程就废了,
*只能用在固定的单一场景的线程不是好线程,所以我们先不重写run方法,先不上枷锁
*/
public class Thread implements Runable{
public void run(){}
}
- Jump类实现同一接口
/**
* Jump实现跟Thread一样的接口,它跟Thread的关系有点像手机充电插头与手机凹槽的区别.
*/
public class Jump extends implements Runable{
private String name = null; //跳船者的姓名,本来想设性别属性,但性别完全可以用子类的命名体现
//比如class BoyJump extends Jump,一眼就看出子类性别是boy
//简单地重写下run方法
@override
public void run(){
System.out.println(“You jump,I jump!”);
}
}
- JumpThread继承Thread类
public class JumpThread extends Thread{
private Object uniObj;
public JumpThread(Object realObj){
this.uniObj = realObj; //享元模式常用的骚操作,将要操作的对象作为参数放入构造方法中
//方便JumpThread;类操作realObj对象的方法与属性.
}
@override
public void run(){ //这一行的run是继承自Thread类的run
uniObj.run(); /*
这一行的run可以是Jump类的run,虽然代码中没有Runable这个接口名出现
但是我们要心知肚明,正是通过Runable接口,Thread类的run方法与Jump类的
run方法耦合到了一起,好处一是松耦合,二是这样一来Thread可以灵活启动不同
的场景,除了Jump,还可以是DownLoad,Copy,Transmit等待,非常方便
*/
}
}
- 给Jump设个具体的子类
/**
*类名BoyJump表示是男性跳船者
*/
public class BoyJump extends Jump{
String name = “Jack”; //男主角Jack
float liveProbality = 0.5 ;//Jack跳船生存的概率
//run()方法有需要可以在Jump类的基础上写得再详细点
@override
public void run(){
System.out.println("Rose,You Jump,I Jump!");
}
}
- 至此所需模块全部写好,编写Tset类运行下
import JumpThread;
import BoyJump;
@Test
public class BoyJumpThreadTest{
public void main(String[] args){
/*
嵌套多态,JumpThread是对Thhread的多态,BoyJump是对Jump的多态
好处是可以针对性地访问子类里从父类继承并重写的方法,或父类自身的方法
这样一来,我想用线程运行DownLoad功能时,写个txtDownLoad类,并在JumpThread的构造方法里
把new BoyJump()替换成new txtDownLoad()即可让线程实现动态变换多种功能
*/
Thread boyJumpThread = new JumpThread(new BoyJump()); //不继承BoyJump类也能调用到BoyJump类的方法,代理模式常用的骚操作.
boyJumpThread.start(); //实际执行的是BoyJump里的run方法
try {
Thread.sleep(2000);
boyJumpThread.interrupt();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
总结:
线程是用来运行具体功能的.传统的写法需要在JumpThread类里重写run方法,大大限制了类的拓展与复用,即JumpThread类只能运行单一的方法集(写死了),太浪费了.
一句话总结我的核心思想:
将已经重写了run方法的具体Jump类的实例作具体Thread类构造方法的实参,从而在具体Thread类里的run方法中调用该实例的run方法.间接实现多态.
我的设计模式属于先向Thread类的构造方法传入具体的Jump类对象,再去做某事.这里的某事既可以是BoyJump,也可以是GirlJump,不会出现把JumpThread类写死的情况! 即符合人脑直觉做事法(线程调用具体对象做具体的事,而不是线程亲自做事),又符合松耦合,方便拓展(线程构造方法换个调用对象便能实现其他功能,非常方便),模块复用的要求.是典型的多态思想.
顺便提一下:OOP的三大特性,多态,继承,封装.为什么OOP的三大特性是它们呢? 因为我们写面向对象的程序时,几乎每一种设计模式都会同时用到这三大概念.而在三大特性之上的抽象更是整个计算机科学的十大思想之一.23种设计模式,样样都有抽象,继承,多态,封装的痕迹.