您的位置:首页 > 其它

面向对象五大原则_3.依赖倒置&4.接口隔离

2015-07-13 21:01 459 查看



依赖倒置原则:Dependence Inversion Principle,DIP

1.高层模板不依赖低层模板,俩者依赖抽象
2.抽象不依赖细节
3.细节依赖抽象

翻译成java风格就是: 面向接口编程
模块间的依赖通过接口或抽象类产生
接口和抽象类不依赖与实现类
实现类依赖接口或抽象类

倒置是什么?
倒置的反义词就是正置,类间实实在在的依赖,例如开奔驰,奔驰就是实在,面向实现编程,正常人的思维,而倒置,对现实事物进行抽象,根据系统设计产生了抽象间的依赖。

悟:这样看起来就是一个工程师在画图,具体不管如何实行,只管大体布局。 这才是领导者干的事!

依赖倒置好处?
采用依赖倒置可以减少类间的耦合性,提高系统的稳定性,降低并行开发引起的风险,提高代码的可读性和维护性。

并行开发?
并行开发最大的风险就是风险扩散,本来只是一段程序的错误或异常,逐渐波及一个功能,一个模块,为什么? 因为在大型项目中,不同的人负责不同的模块,完成的速度有所不同,如果在甲没有完成下乙是不能完全的编码的,开发就是单线程了,甲做完了乙再做......
一个人再牛也不能了解所有业务和技术,要协作就要并行开发,要并发就要解决模块之间的项目依赖关系。 这个时候就需要依赖倒置了。

如何在一方没有完成下进行测试?
俩个类之间有依赖关系,只要制定了倆者之间的接口(或抽象类)就可以独立开发了,而且项目之间的单元测试也可以独立的运行,而TDD(Test-Driven Development,测试驱动开发)开发模式就是依赖倒置的最高级应用。 可以引入一个JMock工具,可以根据抽象虚拟一个对象进行测试。代码可以在《设计模式之禅》代码清单3-10
。 TDD的精髓:测试驱动开发,先写好单元测试类,然后再写实现类,对提高代码质量非常有帮助,适合研发类项目或在项目成员整体水平比较低的情况下采用。

抽象是对现实的约束,只要抽象这根基线在,细节就脱离不了这个圈圈。

依赖的三种写法:

1.构造函数传递依赖对象

public interface IDriver {
 public void drive();
}


public interface ICar {
 public void run();
}


public class Driver  implements IDriver{
 private ICar car;
 public Driver(ICar car){
  this.car=car;
 }
 public void drive() {
  this.car.run();
 }
   
}

2.Setter方法创建依赖对象

public interface IDriver {
 public void drive();
 public void setCar(ICar car);
}


public interface ICar {
 public void run();
}


public class Driver  implements IDriver{
 private ICar car;
 public void drive() {
  this.car.run();
 }
 public void setCar(ICar car) {
  this.car=car;
 }
}

3.接口声明依赖对象

最后尽量遵循以下的原则:
1.每个类尽量都有接口或者抽象类,或倆者兼备,这个嘛,好有根,代码维护。
2.变量的表面类型尽量是接口或者抽象类,就是多态啦。
3.任何类都不应该从具体类派生,和差不多。

在设计的使用,先设计接口,然后分发任务,参数尽量使用接口名称,灵活,扩展性好。

接口隔离原则

Clients should not be forced to depend upon interfaces that they don't use.客户端不应该依赖它不需要的接口
The dependency of one class to another one should depend on the smallest possible interface.类间的依赖关系应该建立在最小的接口上。

接口设计功能不要过于庞大,一个子模块对应一个接口
例如下面的例子星探找美女。



一个美女需要有好看的脸蛋,身材和脾气。
然而这里一个接口就给定了,美女分为俩类,一种是气质型,一种是外貌性,这里显然接口设计功能过多了。 于是拆分为俩个专门的接口。



通过这样的重构以后,不管以后是要气质美女还是要外形美女,都可以保持接口的稳定。当然,你可能要说了,以后可能审美观点再发生改变,只有脸蛋好看就是美女,那这个
IGoodBody接口还是要修改的呀,确实是,但是设计是有限度的,不能无限地考虑未来的变更情况,否则就会陷入设计的泥潭中而不能自拔。

public interface IShapeGirl {
	public void niceBody();
	public void niceCheek();
}
public interface ITemperamentGirl {
	public void goodTemperament();
}


public class PrettyGirl implements IShapeGirl, ITemperamentGirl {
	private String name;
	public PrettyGirl(String name){
		this.name=name;
	}
	public void niceBody() {
		System.out.println(name+"身材好");
	}
	public void niceCheek() {
		System.out.println(name+"脸蛋好");
	}
	public void goodTemperament() {
		System.out.println(name+"气质好");
	}
}


public abstract class Xingtang {
	protected PrettyGirl girl;
	
	public Xingtang(PrettyGirl girl) {
		this.girl=girl;
	}
	public abstract void pick();
}
public class Search extends Xingtang {
	 
	public Search(PrettyGirl girl) {
		super(girl);
	}

	@Override
	public void pick() {
		 girl.niceBody();
		 girl.niceCheek();
		 girl.goodTemperament();
	}
}
public class Client {
	public static void main(String[] args) {
		PrettyGirl g=new PrettyGirl("嫣然");
		Search search=new Search(g);
		search.pick();
	}
}


接口设计尽量"小"
核心,小,有个度,不能违背单一职责原则,如果无限拆分,结构复杂,开发难度增加,那么维护非常麻烦。 "小"是基于业务逻辑来的,基于子模块的功能来的。 不能无限拆分。

接口要"高内聚"
高内聚: 例如你找人去帮一件事,他二话不说立马就给你办成了,这就是高内聚。 体现在java上就是在接口中尽量少公布public方法,接口是对外的承诺,一般是不修改的。
承诺越少对系统开发越有利,变更的风险越少。

定制服务
这个是针对特殊情况而做的改善做法,例如走后门。

悟: 依赖倒置和接口隔离? 都是对关系的总结和抽象,一个是关系处理,一个是内部优化,依赖倒置常用招数就是多态,适配器结构,用于发送尚方宝剑,哪个小弟拿到了就可以代表皇帝了,而接口隔离,这就是一个军情处,神秘的很,同时也很强大,办事效率高,只针对情报,其余不管。


参考资料:《设计模式之禅》

我是菜鸟,我在路上。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: