设计模式:adapter、decorator、strategy、template、 iterator/iterable、factory method、visitor:
创建型模式
工厂方法模式(factory)
当 client 不知道要创建哪个具体类的实例,或者不想在 client 代码中 指明要具体创建的实例时,用工厂方法。定义一个用于创建对象的接口,让其子类来决定实例化哪一个类,从而使一个类的实例化延迟到其子类
例子如下:
interface TraceFactory {
public Trace getTrace();
public Trace getTrace(String type) ;
void otherOperation(){};
}
public class Factory2 implements TraceFactory {
public getTrace(string type) {
if(type.equals(file))
return new FileTrace();
else if (type.equals("system”))
return new SystemTrace();
}
结构型模式
适配器adapter:
将某个类/接口转换为 client 期望的其他形式,通过增加一个接口,将已存在的子类封装起来,cliet面向接口编程,从而隐藏了具体子类
interface Shape {
void display(int x1, int y1, int x2, int y2);
}
Adaptor类实现抽象接口
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(xi, y1, x2,y2);
}
}
对抽象接口编程,与LegacyRectangle隔离
装饰器 decorator
用每个子类实现不同的特性 对每一个特性构造子类,通过委派机制增加到对象上
interface Stack {
void push( Item e);
Item pop( );
}
下面给出一个用于decorator的基础类
public abstract class StackDecorator implements Stack {
protected final stack stack;
public StackDecorator(Stack stack) {
this.stack = stack; Delegation
}
public void push(Item e) {
stack.push(e);
}
public Item pop() i
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);
}
行为类模式
策略 strategy
有多种不同的算法来实现同一个任务,但需要client根据需要动态切换算法,而不是写死在代码里,为不同的实现算法构造抽象接口,利用 delegation,运行时动态传入 client 倾向的算法类实例
public interface PaymentStrategy {
public void pay(int amount);
}
public class PaypalStrategy implements PaymentStrategy {
private String emailId;
private String password;
public PaypalStrategy(String email, String pwd){
this.emailId=email;
this.password=pwd;
}
@Override
public void pay(int amount) {
System.out.println(amount + " paid using Paypal.");
}
}
public class ShoppingCart {
...
public void pay(PaymentStrategy paymentMethod){
int amount = calculateTotal();
paymentMethod.pay(amount);
}
}
客户端:
public class ShoppingCartTest {
public static void main(String[] args) {
ShoppingCart cart = new ShoppingCart();
Item item1 = new Item("1234",10);
Item item2 = new Item("5678",40);
cart.addItem(item1);
cart.addItem(item2);
//pay by paypal
cart.pay(new PaypalStrategy("myemail@exp.com", "mypwd"));
//pay by credit card
cart.pay(new CreditCardStrategy(“Alice", "1234", "786", "12/18"));
}
}
模板(Template)
做事情的步骤一样,但具体方法不同,共性的步骤在抽象类内公共实现,差异化的步骤在各个子类中实现,使用继承和重写实现模板模式
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();
}
}
利用重写子类的方法实现
public class NetOrder
extends OrderProcessTemplate {
@Override
public void doSelect() { ... }
@Override
public void doPayment() { ... }
@Override
public void doDelivery() { ... }
}
迭代 (iterator)
客户端希望遍历被放入容器/集合类的一组 ADT 对象,无需关心容器的具体类型,也就是说,不管对象被放进哪里,都应该提供同样的遍历方式
让自己的集合类实现 Iterable 接口,并实现自己的独特 Iterator 迭代 器(hasNext, next, 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) { ... }
访问
对特定类型的 object 的特定操作(visit),在运行时将二者动态绑定到 一起,该操作可以灵活更改,无需更改被 visit 的类将数据和作用于数据上的某种/些特定操作分离开来为ADT预留一个将来可扩展功能的“接入点”,外部实现的功能代码 可以在不改变 ADT 本身的情况下通过 delegation 接入ADT
public interface ShoppingCartVisitor {
int visit(Book book);
int visit(Fruit fruit);
}
public class ShoppingCartVisitorImpl implements ShoppingCartVisitor {
public int visit(Book book) {
int cost=0;
if(book.getPrice() > 50){
cost = book.getPrice()-5;
}else
cost = book.getPrice();
System.out.println("Book ISBN::"+book.getIsbnNumber() + " cost ="+cost);
return cost;
}
public int visit(Fruit fruit) {
int cost = fruit.getPricePerKg()*fruit.getWeight();
System.out.println(fruit.getName() + " cost = "+cost);
return cost;
}
}