软件构造 4-3 Design Patterns for Reuse

4.3 面向复用的设计模式

一. 模式

  

  • 创建模式
  • 结构模式
  1. 适配器模式
  2. 装饰模式
  3. 门面/外观模式
  • 行为模式
  1. 策略模式
  2. 模板模式
  3. 迭代器模式

1. 结构型模式

1.1 适配器模式

  解决接口不匹配的情况。也可以说是将某个类/接口转换为 client 期望的其他形式。

  • 通过增加一个接口,将已存在的子类封装起来, client 面向接口编程,从而隐藏了具体子类。
    在这里插入图片描述
      如下是参数不匹配的例子(属接口不匹配),通过适配器(中转的类,将不适合的接口变得适合):
    在这里插入图片描述
      源程序:
class LegacyRectangle {
	void display(int x1, int y1, 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 LegacyRectangle {
	void display(int x1, int y1, int w, int h) {...}
}
class Client {
	Shape shape = new Rectangle();
	public display() {
		shape.display(x1, y1, x2, y2);
	}
}
1.2 装饰模式

  为对象增加不同侧面的特性。对每一个特性构造子类,通过委托机制增加到对象上。
在这里插入图片描述
  

interface Stack {
	void push(Item e);
	Item pop();
}
public class ArrayStack implements Stack {
	... //rep
	public ArrayStack() {...}
	public void push(Item e) {
		...
	}
	public Item pop() {
		...
	}
	...
}

public abstract class StackDecorator implements Stack {
	protected final Stack stack;
	public StackDecorator(Stack stack)
		this.stack = stack;
	}
	public void push(Item e) {
		stack.push(e);
	}
	public Item pop() {
		return stack.pop();
	}
	...
}

public class UndoStack extends StackDecorator implements Stack {
	private final UndoLog log = new UndoLog();
	public UndoStack (Stack stack) {
		super(stack);
	}
	public void push(Item e) {
		log.append(UndoLog.PUSH, e);
		super.push(e);
	}
	public void undo() {
		//implement decorator behaviors on stack
	}
	...
}

  层层包装形式使用:

Stack s = new ArrayStack();//普通
Stack t = new UndoStack (new ArrayStack());//undo stack
Stack t = new SecureStack(new SynchronizedStack(new UndoStack(s));//secure synchronized undo stack

  层层包装有所限制,无法使用包装内部的方法,只能使用显式(接口)的方法。

  Collections 提供的包装类提供的是引用,一个指向原 ListSetMap 的对象。

1.3 外观/门面模式

  客户端需要通过一个简化的接口来访问复杂系统内的功能。
  提供一个统一的接口来取代一系列小接口调用,相当于对复杂系统做了一个封装,简化客户端使用。

public class MySqlHelper {
	public static Connection getMySqlDBConnection() {...}
	public void generateMySqlPDFReport(String tableName, Connection con) {...}
	public void generateMySqlHTMLReport(String tableName, Connection con) {...}
}
public class OracleHelper {
	public static Connection getOracleDBConnection() {...}
	public void generateOraclePDFReport(String tableName, Connection con) {...}
	public void generateOracleHTMLReport(String tableName, Connection con) {...}
}

public class HelperFacade {
	public static void generateReport(DBTypes dbType, ReportTypes reportType, String tableName){
		Connection con = null;
		switch (dbType){
		case MYSQL:
			con = MySqlHelper.getMySqlDBConnection();
			MySqlHelper mySqlHelper = new MySqlHelper();
			switch(reportType){
				case HTML:
					mySqlHelper.generateMySqlHTMLReport(tableName, con);
					break;
				case PDF:
					mySqlHelper.generateMySqlPDFReport(tableName, con);
					break;
			}
			break;
			case ORACLE: ...
	}
	public static enum DBTypes { MYSQL,ORACLE;}
	public static enum ReportTypes { HTML,PDF;}
}

2. 行为型模式

2.1 策略模式

  有多种不同的算法来实现同一个任务,但需要 client 根据需要动态切换算法,而不是写死在代码里。

  为不同的实现算法构造抽象接口,利用 delegation ,运行时动态传入 client 倾向的算法类实例。

2.2 模板模式

  做事情的步骤一样,但具体方法不同。共性的步骤在抽象类内公共实现,差异化的步骤在各个子类中实现。

  方法是:使用继承和重写实现模板模式。(白盒框架

  注:final 可以限制方法,不让它被重写。

public abstract class OrderProcessTemplate {
	public boolean isGift;
	public abstract void doSelect();
	public abstract void doPayment();
	public final void giftWrap() {
		System.out.println("Gift wrap done");
	}
	public abstract void doDelivery();
	public final void processOrder() {
		doSelect();
		doPayment();
		if (isGift)
			giftWrap();
		doDelivery();
	}
}
2.3 迭代器模式

  客户端希望遍历被放入容器/集合类的一组 ADT 对象,无需关心容器的具体类型

  • 也就是说,不管对象被放进哪里,都应该提供同样的遍历方式

在这里插入图片描述
  集合端继承Iterable 接口,使实现该接口的集合对象是可迭代遍历的

public interface Iterable<T> {
	...
	Iterator<T> iterator();//返回指向当前集合的迭代器
}

  Iterator 接口:迭代器

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

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

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

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

  迭代器类是 immutable 类型。使得 remove 操作元素时,只能使用迭代器的 remove 操作。

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 PairIterator 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; return second; }
			throw new NoSuchElementException();
		}
		public void remove() {
			throw new UnsupportedOperationException();
		}
	}
}
Pair<String> pair = new Pair<String>("foo", "bar");
for (String s : pair) {}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值