三、原则
1、开闭原则:
当一个继承结构已经存在时,可以增加新的类型到该结构中(开),但不应该对原有结构进行修改(闭);
实现前提:将类功能中可变(方法的功能)和不变的元素(比如方法的名字)分离,彻底的分离是将上层类型设计
为抽象的;
2、里氏代换原则:
里氏代换原则的严格表达是:如果对每一个类型为T1的对象o1,都有类型为T2的对象o2,使得以T1定义的
所有程序P在所有的对象o1都代换成o2时,程序P的行为没有变化,那么类型T2是类型T1的子类型
换言之,一个软件实体如果使用的是一个基类的话,那么一定适用于其子类,而且它根本不能察觉出基类对象
和子类对象的区别。
从抽象类的继承:如果有一个由继承关系形成的等级结构的话,那么在等级结构的树图上面所有的树叶节点都
应当是具体类;而所有的树枝节点都应当是抽象类或者Java接口
3、依赖倒转原则:
什么是依赖倒转原则:简单地说:依赖倒转原则要求客户端依赖于抽象耦合。
依赖倒转原则的表述是:抽象不应该依赖于细节;细节应当依赖于抽象。
另一种表述是:要针对接口编程,不要针对实现编程。
只要一个被引用的对下个存在抽象类型,就应当在任何引用此对象的地方使用抽象类型,包括参数的类型声明、
方法返回类型的声明、属性变量的类型声明等。
Java语言中创建一个对象的过程是违背“开-闭”原则以及依赖倒转原则的。正是由于这个原因,设计模式给
出了多个创建模式,特别是几个工厂模式,用于解决对象创建过程中的依赖倒转问题。
依赖倒转原则的优缺点:
依赖倒转原则虽然很强大,但却是最不容易实现的。因为依赖关系倒转的缘故,对象的创建很可能要使用对象
工厂,以避免对具体类的直接引用,此原则的使用还会导致大量的类。对不熟悉面向对象技术的工程师来说,
维护这样的系统需要较好的面向对象的设计的知识。此外,依赖倒转原则假定所有的具体类都是会变化的,这
也不总是正确的。有一些具体类可能是相对稳定、不会发生变化的,消费这个具体类实例的客户端完全可以依
赖于这个具体类型,而不必为此发明一个抽象类型
4、接口隔离原则:
接口间隔原则讲的是:使用多个专门的接口比使用单一的接口要好。
换言之,从客户类的角度来讲:一个类对另外一个类的依赖性应当是建立在最小的接口上的。
接口污染:每个接口代表一个角色,不要想着节省接口的数目,把看上去相似的接口合并为一个接口,这样会
形成一个臃肿的大接口,是对角色和接口的污染。
角色分割。
定制服务也是一个重要的设计原则。他的意思是说,如果客户端仅仅需要某一些方法的话,那么就应当向客户
端提供一些需要的方法,而不要提供不需要的方法。这样做的效果是:1、这样做很整洁。2、系统的可维护性。
5、组合/聚合复用原则:
合成/聚合复用原则就是在一个新的对象里面使用一些已有的对象,使之成为新对象的一部分;新的对象通过
向这些对象的委派达到复用已有功能的目的。简短的表述:要尽量使用合成/聚合,尽量不要使用继承
合成/聚合复用
优点:1、新对象存取成分对象的唯一方法是通过成分对象的接口。2、这种复用是黑箱复用,因为成分对象的
内部细节是新对象看不见的。3、这种复用支持包装。4、这种复用所需的依赖较少。5、每一个新的类可以将
焦点集中在一个任务上6、这种复用可以在运行时间内动态进行,新对象可以动态地引用与成分对象类型相同
的对象。
通过继承达到复用的目的
尽管继承是一种非常重要的复用手段,但是设计师应当首先考虑使用合成/聚合,而不是继承。
继承复用的优点:利用继承关系达到复用的做法有下面的优点:1、新的实现较容易,因为超类的大部分功能
可以通过继承关系自动进入子类。2、修改或扩展继承而来的实现较为容易。
继承复用的缺点:与合成/聚合复用不同,继承有多个缺点:1、继承复用破坏包装,因为继承将超类的实现细
节暴露给子类。由于超类的内部细节常常是对子类透明的,因此这种复用是透明的复用,又称“白箱”复用。
2、如果超类的实现发生改变,那么子类的实现也不得不发生改变。因此,当一个基类发生改变时,这种改变
会像水中投入石子引起的水波一样,将变化一圈又一圈的传导到一级又一级的子类,使设计师不得不相应的改
变这些子类,以适应超类的变化。3、从超类继承而来的实现是静态的,不可能在运行时间内发生改变,因此
没有足够的灵活性。
从代码重构的角度理解
对违背里氏代换原则的设计进行重构时,可以采用两个方法:一是加入一个抽象超类,二是将继承关系改写成
合成/聚合关系。
区分“Has-A”于“Is-A”
“Is-A”是严格的分类学意义上的定义,意思是一个类是另一个类的“一种”(只有当每一个S在任何情况下都
是一种B的时候,才可以将S设计成B的子类)(API的反例properties继承Hashtable违反了里氏代换原则,
它们是“Has-A”的关系)。而“Has-A”则不同,它表示某一个角色具有某一项责任
6、迪米特法则
迪米特法则又叫做最少知识原则就是说,一个对象应当对其他对象有尽可能少的了解。
所谓调用转发,需要隐藏“陌生人”的存在,使得“某人”仅知道“朋友”,而不知道“陌生人”;换言之,
“某人”会认为他所调用的这个方法是“朋友”的方法。
狭义的迪米特法则会产生一个明显的缺点:会在系统里面造出大量的小方法,散落在系统的各个角落。这些方
法仅仅是传递间接的调用,因此与系统的商务逻辑无关。
广义的迪米特法则
其实,迪米特法则所谈论的,就是对对象之间的信息流量、流向以及信息的影响的控制。
迪米特法则的主要用意是控制信息的过载。在将迪米特法则运用到系统设计中时,要注意下面的几点:
1、在类的划分上,应当创建有弱耦合的类。类之间的耦合越弱,就越有利于复用。一个处在弱耦合中的类一
但被修改,不会对有关的类造成波及。
2、在类的结构设计上,每个类都应当尽量降低成员的访问权限。换言之,一个类包装好各自的private状态
(自己的“秘密”)。这样一来,想要了解其中的一个类的意义时,不需要了解很多别的类的细节。一个类不
应当public自己的属性,而应当提供取值和赋值方法让外界间接访问自己的属性。
3、在类的设计上,只要有可能,一个类应当设计成不变的类。
4、在对其他类的引用上,一个对象对其对象的引用应当降到最低。
四、模式
工厂方法模式
组成:
抽象工厂:定义工厂应有的方法
具体工厂:继承抽象工厂,实现抽象工厂定义的方法,用于返回具体产品,一般每个具体工厂返回特定类型的
产品;
抽象产品:定义产品应有的方法;
具体产品:继承抽象产品,实现抽象产品定义的方法,完成产品的所有功能;
使用的设计原则:开闭原则,里氏代换原则,依赖倒转原则;
单例模式
对于某个类型只需要创建一个对象
方法:
1.创建一个私有构造器;
2.创建一个私有的静态的属性,类型为当前类;
3.创建一个共有的静态的方法,用于返回私有静态属性;
public class Company{
private Company(){}
private static Company instance=new Company();
public static Company getInstance(){
return instance;
}
}
public class Company{
private Company(){}
private static Company company=null;;
public synchronized static Company getIntance(){
if(company==null){
return new Company();
}
return null;
}
}
组合模式
在父类下存在两种类型的子类,一种是普通的子类(叶子),另一种是复合子类(可以作为容器,容纳的元素为父
类类型)
Component(组件) 父类
Container extends Component 复合子类
Button extends Component 普通子类
TextFiled extends Component 普通子类
.....
观察者模式
使用方式
1.使用抽象类维护观察者列表,该抽象类是被观察对象的根;(不变元素)
2.继承该抽象类,实现被观察对象的具体方法;(可变元素)
3.观察者对象通过注册的方式向被观察者提交请求;
4.当特定事件发生后,被观察者对象通知所有观察者对象;
MVC模式
当前使用最多的MVC模式是基于Web的MVC,在保留MVC模块分离特性的基础上,
内部信息传递主要由Web组件实施(Web Server);
传统的MVC需要由开发人员完成所有的功能,包括信息传递,Swing API的开发基于传统MVC实现;
MVC的正真目的是数据信息的重用性和可维护性,从表面上看,表现为显示格式View和数据信息Model的
分离;
重用性:相同的数据信息可以提供给多个View使用;
可维护性:对于多个显示相同信息的View,只需要对一份数据进行维护,最大程度降低数据不一致的可能;
传统的MVC将Model作为被观察者,View作为观察者,所有View对其观察的Model进行注册,当Model数
据改变时通知观察者列表中所有的View,View根据具体的Model信息对页面进行更新;
基于Web的MVC由于Web需要请求相应机制才能对显示的信息进行更新,所以更新信息会相对滞后,Ajax
的推出部分解决了该问题;
状态模式
特点:对象的行为不再有对象决定(oo的设计思想是对象的行为作为该类的方法),改由状态决定;
解决方案:
1.创建主对象(状态图中描述的对象),将所有行为定义为该类的方法;
2.主对象中保存对象的状态信息;
3.状态信息通过类实现,每种状态对应一个类,通常所有的状态类继承相同的父类(状态类的根),设计父类和
子类时同样基于分离可变和不变元素的思想;
4.状态类中定义主对象中的所有行为对应的方法,主对象根据当前状态,调用相应状态类中的对应方法;
---------------------------------------------------------------------------------------------------
分析阶段类定义只需要必要的属性和业务方法;
设计阶段对属性进行封装,并可视需求增加推导属性以及对业务方法进行筛选和增加;
---------------------------------------------------------------------------------------------------
关联关系的代码实现
普通关联:通过set方法建立关联
聚合:通过构造器建立关联
组合:通过构造器建立关联
组合和聚合的区别:
聚合:通过构造器建立关联,包含对象作为构造器参数传入,在构造器中实现关联关系;
组合:通过构造器建立关联,包含对象的创建信息作为构造器参数传入,在构造器建立包含对象,
然后实现关联关系(强调生命周期);
OOA&OOD(二)
最新推荐文章于 2022-04-27 18:06:51 发布