【软件构造】软件构造复习总结3-第四、五章部分

【软件构造】软件构造复习总结3-第四、五章部分

第四五章主要复习了各种设计模式。

第四章
一、可复用性的度量、形态学和外部观察
1.源代码复用;模块复用(类或接口);库复用(API);系统复用(框架)。
2.白盒框架:通过继承和动态绑定实现可扩展性,通过继承框架基类并重写预定义的钩子方法来扩展现有功能
3.黑盒框架:通过定义符合特定接口的组件来重用现有功能,这些组件通过委托与框架集成
二、面向复用的软件构造技术
1.LSP:在任何父类型可一应用的场景,子类型都可以应用。
重写的方法可以有相同的前置和后置条件。也可以有更弱的前置条件或更强的后置条件。
在这里插入图片描述
2.协变:父类型->子类型:越来越具体specific 返回值类型:不变或变得更具体异常的类型:也是如此。如:
在这里插入图片描述
逆变:父类型->子类型:越来越具体specific 参数类型:要相反的变化,要不变或越来越抽象。如:
在这里插入图片描述
3.泛型中的LSP:ArrayList是List的子类,ArrayList不是List的子类。
例.

static long sum(List<Number> list) {
		long sum = 0;
		for(Number number : list) {
			sum+= number.longValue();
		}
		return sum;
}
public static void main(String[] args){
		List<Integer> list = List.of(1,2,3);
		System.out.println(sum(list));
}

Sum会报错:
在这里插入图片描述
不可以认为List是List的子类进行传入。
4.<?>通配符:使用例子:
在这里插入图片描述在这里插入图片描述

客户端:

public static void main(String[] args){
		List<Integer> li = Arrays.asList(1, 2, 3); 
		List<String>  ls = Arrays.asList("one", "two", "three"); 
		printList(li); 
		printList(ls);
}

printList的目标是打印任何类型的列表,但是它无法实现这个目标-它只打印对象实例的列表;它不能打印list、list和list等等,因为它们不是list的子类型。
要编写通用的printList方法,使用List<?>。
控制台:
在这里插入图片描述
5.<? super A>与 <? extends A> :如:
在这里插入图片描述
前者只匹配整数类型的列表,而后者匹配整数超类型(如Integer、Number和Object)的任何类型的列表。
5.Comparator<…>接口,如果ADT需要比大小可以实现该接口并override compareTo(Object o)或compare(Object o1, Object o2)函数。
可以使用Collections.sort(this.o);进行排序
6.委派(delegation):一个对象请求另一个对象的功能。
7.CRP(复合重用原则):类应该通过组合所需功能,而不是通过继承来实现多态和复用。重点理解:
在这里插入图片描述
8.各种委派:
a.Dependency: 临时性的delegation,如:
在这里插入图片描述
b.Association: 永久性的delegation,如:
在这里插入图片描述
c. Composition: 更强的association,但难以变化,如:
在这里插入图片描述
d.Aggregation: 更弱的association,可动态变化,如:
在这里插入图片描述
三、面向复用的设计模式
1.Structural patterns 结构型模式:处理类或对象的组合。
a.Adapter适配器模式:将某个类/接口转换为client期望的其他形式.
通过增加一个接口,将已存在的子类封装起来,client面向接口编程,从而隐藏了具体子类。
在这里插入图片描述
b. Decorator装饰器模式:为对象增加不同侧面的特性.
对每一个特性构造子类,通过委派机制增加到对象上
在这里插入图片描述
例子类比:
在这里插入图片描述
Decorator通过delegate到stack完成基本操作,在decorator基础上通过继承增添新的功能。
c. Facade外观模式:客户端需要通过一个简化的接口来访问复杂系统内的功能。
提供一个统一的接口来取代一系列小接口调用,相当于对复杂系统做了一个封装,简化客户端使用。
2.Behavioral patterns 行为类模式:描述类或对象交互和分配责任的方式。
a. Strategy策略模式:为不同的实现算法构造抽象接口,利用delegation,运行时动态传入client倾向的算法类实例。
在这里插入图片描述
b.Template Method模板模式:共性的步骤在抽象类内公共实现,差异化的步骤在各个子类中实现。
在这里插入图片描述
与白盒框架类似。
c. Iterator迭代器:客户端希望遍历被放入容器/集合类的一组ADT对象,无需关心容器的具体类型。
在这里插入图片描述
主要实现方式:两个接口,Iterable和Iterator。
在这里插入图片描述在这里插入图片描述

自己的类实现Iterable接口,并创造一个新类实现迭代器。
遍历:
在这里插入图片描述
以实验为例,实验中让实现board的迭代。
首先创造一个BoardIterator实现Iterator接口

public class BoardIterator implements Iterator<PlanningEntry<Resource>>{
	private PlanningEntryCollection pec;
	private int count = 0;
	
	// Abstraction function:
    //	 AF(BoardIterator)={pec , count| pec映射是一系列计划项,count映射是第几个计划项}
    // Representation invariant:
    //   nothing
    // Safety from rep exposure:
    //   所有变量都是private的
    //
	
	/**
	 * BoardIterator的构造器
     * @param pec 一系列计划项
	 * 
	 */
	public BoardIterator(PlanningEntryCollection pec) {
		this.pec = pec;
		Collections.sort(this.pec.getPes());
	}
	
	/**
	 * 
     * @return boolean
	 * 
	 */
	@Override
	public boolean hasNext() {
		return count < pec.getPes().size();
	}

	/**
	 * 
     * @return PlanningEntry<Resource>
	 * 
	 */
	@Override
	public PlanningEntry<Resource> next() {
		PlanningEntry<Resource> n = pec.getPes().get(count);		
		count++;
		return n;
	}

	/**
	 * 
	 * 
	 */
	@Override
	public void remove() {
		throw new UnsupportedOperationException();
	}
}

接下来Board实现Iterable接口

public abstract class Board implements Iterable<PlanningEntry<Resource>>{
	private PlanningEntryCollection pec; 
	
	// Abstraction function:
    //	 AF(Board)={pec | pec映射是一系列计划项}
    // Representation invariant:
    //   nothing
    // Safety from rep exposure:
    //   所有变量都是private的
//
......
......
/**
	 * 迭代器
     * @return Iterator<PlanningEntry<Resource>>
     */
	@Override
	public Iterator<PlanningEntry<Resource>> iterator() {
		return new BoardIterator(pec);
	}
}

第五章
一、高可维护性的度量与构造原则
1.高内聚,低耦合:
在这里插入图片描述
2.SOLID原则:
a.SRP(单一责任原则):不应有多于1个的原因使得一个类发生变化;一个类,一个责任。
b.OCP((面向变化的)开放/封闭原则):
对扩展性的开放:模块的行为应是可扩展的,从而该模块可表现出新的行为以满足需求的变化。
对修改的封闭:模块自身的代码是不应被修改的;扩展模块行为的一般途径是修改模块的内部实现;如果一个模块不能被修改,那么它通常被认为是具有固定的行为。
用抽象方法解决。同时解决了(if/else/switch太多维护困难的问题)
c.LSP(Liskov替换原则):同第四章。
d.ISP(接口隔离原则):客户端只访问自己所需要的端口。
反面例子:
在这里插入图片描述
修改后:
在这里插入图片描述
e.DIP(依赖转置原则):抽象的模块不应依赖于具体的模块;具体应依赖于抽象。
二、面向可维护性的设计模式
1.工厂方法:
正常客户端:Product p = new ProductTwo();//通过new一个新的对象
工厂方法下:Product p = new ConcreteTwo().makeObject();//通过一个类中的方法创建对象。不暴露内部类的名字。
工厂方法:可以在ADT中也可以单独构建一个类:
在这里插入图片描述
Abstract Factory抽象工厂:把多个工厂方法组合到一起。
2. Proxy代理模式:隔离对复杂 对象的访问,降低难度/代价,定位在“访问/使用行为”
在这里插入图片描述
3.Observer模式:建立对象间一对多的情况。如偶像更新微博,所有的observer自动打印更新的行为。observer关注偶像,偶像的ADT自动将observer加入关注者名单。
4.Visitor模式:对特定类型的object的特定操作(visit),在运行时将二者动态绑定到一起,该操作可以灵活更改,无需更改被visit的类。
特点:在特定ADT上执行某种特定操作,但该操作不在ADT内部实现,而是delegate到独立的visitor对象,客户端可灵活扩展/改变visitor的操作算法,而不影响ADT。
三、面向可维护性的构造技术
1.State模式:state作为一个接口,有不同的实现类,在别的ADT执行完操作通过delegation到具体的state的实现类自动完成状态转换。
在这里插入图片描述
2.正则表达式:
在这里插入图片描述
剩下具体使用在另一篇博客有稍微详细一点的复习。

/***********************************************************************************/
以上即为软件构造复习总结3-第四、五章部分。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值