软件构造复习:第四章(下)

CRP原则

复合重用原则

  • 类应该通过其组合(通过包含实现所需功能的其他类的实例/委托)而不是从基类或父类继承来实现多态行为和代码重用
  • 组合一个对象所能做的事(has_a or use_a)比扩展它所能做的事(is_a)要好。

eg1.计算不同类别员工的年终奖

//通过继承
class Employee{
	Money computeBonus(){...//default computation}
}

//不同类别的员工
class Manager extends Employee{
	@Override
	Money computeBons(){...//special computation}
	...
}
...
//不同类型的manager
class SeniorManager extends Manager{
	@Override
	Money computeBons(){...//more special computation}
	...
}

存在的问题:

  • 更改某个manager的类型时如何处理?
  • 如果两个类型的计算方式一样时,如何处理?复制?
  • 每个Employee对象的奖金计算方法都不同,在object层面而非class层面

A CRP solution

class Employee{
	BonusCalculator bc;
	...
}
|
|Delegation
|
V
interface BonusCalculator{
	Money computeBonus();
}
//Inheritance:继承

class Manager extends Employee{
	Money computeBonus(){
	bc=new ManagerBonusCalculator();
	return bc.computeBonus();
	}
}
|
|Delegation
|
V                            //Implement:接口实现
class ManagerBonusCalculator implements BonusCalculator{

	Money computeBonus{...//special computation}
}

接口的组合

接口之间通过extends实现行为的扩展
接口的组合,定义了行为的组合

白盒框架的原理与实现

白盒框架:通过代码层面的继承进行框架扩展

  • 通过继承动态绑定实现可扩展性
  • 通过子类化(subclassing)重写方法进行扩展
  • 通用设计模式:模板方法
  • 子类有main方法,但控制框架(gives control to framework)
public abstract class PrintOnScreen{
	//main body of framework reuse
	public void print(){
		JFrame frame=new JFrame();
		JOptionPane.showMessageDialog(frame,textToShow());
		frame.dispose();
	}
	//extension point
	protected abstract String textToShow();
}

public class MyApplication entends PrintOnScreen{
	@Override
	protected String textToShow(){
		return "printing this text on"
		      +"screen using PrintOnScreen"
		      +"white Box Framework";
	}
}

MyApplication m=new MyApplication();
m.print();

黑盒框架的原理与实现

黑盒框架:通过实现特定的接口/delegation进行框架扩展

  • 通过可插入框架的组件定义接口来实现可扩展性
  • 通过定义符合特定接口的组件来重用现有功能
  • 通过实现插件接口进行扩展
  • 常见设计模式:策略、观察者
  • 这些组件通过委托与框架集成
  • 插件加载机制(Plugin-loading mechanism)加载插件并控制框架
public final class PrintOnScreen{
	TextToShow textTOShow;
	public PrintOnScreen(TextToShow tx){
		this.textToShow=tx;
	}

	public void print(){
		JFrame frame=new JFrame();
		JOptionPane.showMessageDialog(frame,frame.dispose());
	}
}
public interface TextToShow{
	String text();
}
public class MyTextToShow implements TextToShow{
	@Override
	public String text(){
		returong "Printing";
	}
}
PrintOnScreen m=new PrintOnScreen(new MyTextToShow());
m.print();

设计模式

设计模式更强调多个类/对象之间的关系和交互过程–比接口/类复用的粒度更大

adapter/适配器模式

将某个类/接口转换为client期望的其他形式

  • 解决类之间接口不兼容的问题
  • 通过增加一个接口,将已存在的子类封装起来,client面向接口编程,从而隐藏了具体类。
    在这里插入图片描述
    eg。
//without Adaptor pattern
class LegacyRectangel{
	void display(int x1,int x2,int w,int h){...}
}

class Client{
	public display(){
		new LegacyRectangle().display(x1,y1,x2,y2);//没有办法兼容
	}
}
interface Shape{
	void display(int x1,int y1,int x2,int y2);
}

class Rectangle implements Shape{
	void display(int x1,int y1,int x2,int y2){
		new LegacyRectangle().display(x1,y1,x2-x1,y2-y1);
	}
}
class LegencyRectangle{
	void dispalynew(int x1,int y1,int w,int h);
}

class Client{
	Shape shape=new Rectangle();//与LegacyRectangle隔离
	public display(){
		shape.display(x1,y1,x2,y2);
	}
}

decorator/装饰器模式

  • 为对象增加不同侧面的特性
  • 对每一个特性构造子类,通过委派机制增加到对象上

以递归的方式实现

装饰器模式use both继承机制和委托机制

  • 接口:定义装饰物执行的公共操作
  • 起始对象,在其基础上增加功能(装饰),将通用的方法放到此对象中
  • Decorator抽象类是所有装饰类的基类,里面包含的成员变量component指向了被装饰的对象

在这里插入图片描述
eg。
在这里插入图片描述

public interface IceCream{//顶层接口
	void AddTopping();
}
public class PlainIceCream implements IceCream{//基础实现,无添加的冰激凌
	@Override
	public void AddTopping(){
		System.out.println("Plain IceCream ready for some toppings!");
	}
}

/*装饰器基类*/
public abstract class ToppingDecorator implements IceCream{
	protected final IceCream input;
	public ToppingDecorator(IceCream i){
		this.imput=i;
	}
	public abstract void AddTopping();//留给具体装饰器实现
}

public class CandyTopping extends ToppingDecorator{
	public CandyTopping(IceCream i){
		super(i);
	}

	public void AddTopping(){
		input.AddTopping();
		System.out.println("Candy Topping added!");
	}
}

public class NutsTopping extends ToppingDecorator{
	//similar to CandyTopping
}

public class PeanutTopping extends ToppingDecorator{
	//similar to CandyTopping
}

public class Client{
	public static void main(String[] args){
		IceCream a=new PlainIceCream();
		IceCream b=new CandyTopping(a);
		IceCream c=new PeanutTopping(b);
		IceCream d=new NutsTopping(c);
		d.AddTopping();

		//or
		Icecream toopingIceCream=
			new NutsTopping(
				new PeanutTopping(
					new CandyTopping(
						new PlainIceCream())));
		toppingIceCream.AddTopping();
	}
}
//The result:
//Plain IceCream ready for some toppings!
//Candy Topping added!
//Peanut Topping added!
//Nuts Topping added!

façade/外观模式

客户端需要一个简化的接口来访问复杂系统内的功能

  • 提供一个统一的接口来取代一系列小接口调用,相当于对复杂系统做了一个封装,简化客户端使用
  • 便于客户端学习使用,解耦

在这里插入图片描述
eg。
在这里插入图片描述
查看实例的详解

strategy/策略模式

有多种不同的算法来实现同一个任务,但需要client根据需要动态切换算法,而不是写死在代码里
为不同的实现算法构造抽象函数,利用delegation,运行时动态传入client倾向的算法实例

在这里插入图片描述

template/模板模式

做事情的步骤一样,但具体方法不同

共性的步骤在抽象类内公共实现,差异化的步骤在各个子类中实现

模板方法定义了一个算法的步骤,并允许子类为一个或多个步骤提供实现

使用继承和重写实现模板模式,模板模式在框架(白盒框架)中广泛使用。

在这里插入图片描述

iterator/iterable(迭代器模式)

客户端希望遍历被放入容器/集合类的一组ADT对象,无需关系容器的具体类型
也就是说,不管对象被放进那里,都应该提供同样的遍历方式。

Iterable接口:实现该接口的容器对象是可迭代遍历的

public interface Iterable<T>{
	...
	Iterator<T> iterator();//返回一个迭代器
}

Iterator接口:迭代器

public interface Iterator<E>{
	boolean hasNext();
	E next();
	void remove();
}

Iterator pattern:让自己的集合类实现Iterable接口,并实现自己独特的Iterator迭代器(hasNext,next,remove),允许客户端利用这个迭代器进行显示或隐式的迭代遍历:

for(E e:collection ){...}

Iterator<E> iter=collection.iterator();
while(iter.hasNext()){...}

eg.
在这里插入图片描述

public class Pair<E> implements Iterable<E>{
	private final E first,second;
	public Pair(E f,E s){first=f;second=s;}
	public Iterator<E> iterator(){
		return new PairIterator();
	} 
}

private class PainIterator implements Iterator<E>{
	private boolean seenFirst=false,seenSecond=false;
	public boolean hasNext(){return !seenSecond;}
	public E next(){
		if(!seenFirst){seenFirst=true;return first;}
		if(!seenSecond){seenSecond=true;retun second;}
		throw new NoSuchElementException();
	}
	public void remove(){
		throw new UnsuppportedOperatinException();
	}
}

Pair<String> pair=new Pair<String>("foo","bar");
for(Strig s:pair){...}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值