软件构造复习笔记:Design Patterns for Reuse and Maintainability

一、Factory Method Pattern

        当client不知道或不确定要创建哪个具体类的实例,或者不想再client代码中知名要具体创建的实例时,用工厂方法。

        定义一个用于创建对象的接口,让该接口的子类型来决定实例化哪一个类,从而使一个类的实例化延迟到其子类。

        工厂接口及其实现类:

interface TraceFactory{
    Trace getTrace();
    ...
}

public class SystemTraceFactory implements TraceFactory{
    public Trace getTrace(){
        ...
        return new SystemTrace();
    }
}

public class FileTraceFactory implements TraceFactory{
    public Trace getTrace(){
        ...
        return new FileTraceFactory();
    }
} 

        client:

Trace log1 = new SystemTraceFactory().getTrace();

Trace log2 = new FileTraceFactory().getTrace();

二、Adaptor Pattern

        当某个类的某个方法和client期望的形式冲突时,可以使用Adaptor模式添加适配器。

        如LegacyRectangle类的display(x,y,w,h)方法,四个参数分别表示左上角的坐标、宽、高,而client希望它们表示的是左上角坐标和右上角坐标,这时就可以为display方法添加一个适配器。

        如下,ShapeAdaptor接口中定义需要适配的方法,Rectangle类按client的要求实现该接口中的方法,client使用适配器访问该方法,这样无需修改原LegacyRectangle类就可以做出功能上的改变。若display有多个版本,则为ShapeAdaptor增加子类,在子类中实现各版本。

interface ShapeAdaptor{
    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);
    }
}

三、Decorator

        接口IceCream和它的实现类PlainIceCream,接口定义了一个方法AddTopping,现要扩展AddTopping的功能。可以先定义一个装饰器基类ToppingDecorator,再为各个版本定义子类,子类中通过委派的方式使用原始版本的方法,在其基础上增加一些操作。

        装饰器的有一个input域,可以赋值为原始类,也可以赋值为装饰类,这是递归的形式。

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.input = i;
    } 
    public abstract void AddTopping();
}
/*子类1*/
public class CandyTopping extends ToppingDecorator{ 
    public CandyTopping(IceCream i) { 
        super(i);
}
    public void AddTopping() { 
        input.AddTopping();
        System.out.println("Candy Topping added!");
    } 
}
/*子类2,3*/
public class NutsTopping extends ToppingDecorator{ 
    //similar to CandyTopping
}
public class PeanutTopping extends ToppingDecorator{ 
    //similar to CandyTopping
}

        client根据需要选择装饰器:

IceCream toppingIceCream = 
    new NutsTopping( 
        new PeanutTopping( 
            new CandyTopping( 
                new PlainIceCream()
                ) 
            ) 
    );
toppingIceCream.AddTopping();

四、Strategy Pattern

        某个方法有多种实现,client需要动态切换实现方式。

        现要将类ShoppingCart的pay方法实现为多个版本,创建Strategy接口,定义pay方法,然后在该接口的实现类中实现pay的多个版本,让ShoppingCart类的pay方法接收Strategy实例,调用相应Strategy的pay方法。

public class ShoppingCart { 
    ... 
    public void pay(PaymentStrategy paymentMethod){ 
        ...
        paymentMethod.pay(amount);
    }
}

public interface PaymentStrategy { 
    public void pay(int amount);
}
public class PaypalStrategy implements PaymentStrategy { 
    ...
    @Override 
    public void pay(int amount) { 
        //实现方法一
        System.out.println(amount + " paid using Paypal.");
    }
}
public class CashStrategy implements PaymentStrategy { 
    ...
    @Override 
    public void pay(int amount) { 
        //实现方法二
        System.out.println(amount + " paid using Cash.");
    }
}

        client通过向pay传递Strategy的方式切换不同实现:

ShoppingCart cart = new ShoppingCart();
...
cart.pay(new PaypalStrategy(...));
cart.pay(new CashStrategy(...));

五、Template Method

        若某些类的实现过程步骤相同,只是各个步骤的实现不同,那么就可以将这个步骤抽象成一个接口。

        如接口CarBuilder中定义了三个步骤和一个通用逻辑指示这些步骤的执行顺序,实现类中实现步骤的不同版本。

public abstract class CarBuilder { 
    protected abstract void BuildSkeleton(); 
    protected abstract void InstallEngine(); 
    protected abstract void InstallDoor();

    // Template Method that specifies the general logic 
    public void BuildCar() {
    //通用逻辑
    BuildSkeleton(); InstallEngine(); InstallDoor();
    }
}
public class PorcheBuilder extends CarBuilder { 
    protected void BuildSkeleton() { 
        System.out.println("Building Porche Skeleton");
    } 
    protected void InstallEngine() { 
        System.out.println("Installing Porche Engine");
    } 
    protected void InstallDoor() { 
        System.out.println("Installing Porche Door");
    } 
}
public class BeetleBuilder extends CarBuilder { 
    protected void BuildSkeleton() { 
        System.out.println("Building Beetle Skeleton");
    } 
    protected void InstallEngine() { 
        System.out.println("Installing Beetle Engine");
    } 
    protected void InstallDoor() { 
        System.out.println("Installing Beetle Door");
    }
}

        client:

CarBuilder c = new PorcheBuilder(); 
c.BuildCar();
c = new BeetleBuilder();
c.BuildCar();

六、Iterator Pattern

        将某一个类实现为可迭代类。

        MyArray类实现Iterable接口,重写iterator方法,返回一个迭代器;

        MyIterator为一个自定义迭代器,实现Iterator接口的next、hasNext方法。

public class MyArray<E> implements Iterable<E> {
    private final List<E> list;

    public MyArray(List<E> list) {
        this.list = new ArrayList<E>(list);
    }

    public MyArray() {
        list = new ArrayList<>();
    }

    @Override
    public Iterator<E> iterator() {
        return new MyIterator();
    }

    private class MyIterator implements Iterator<E> {
        private int index;

        public MyIterator() {
            index = 0;
        }

        @Override
        public boolean hasNext() {
            return index < list.size();
        }

        @Override
        public E next() {
            E element = list.get(index);
            index++;
            return element;
        }

    }
}

        client:

public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("a");
        list.add("b");
        list.add("c");
        MyArray<String> mi = new MyArray<>(list);
        for (String s : mi) {
            System.out.println(s);
        }
    }

七、Vistor Pattern

        某个类需要多种访问方式。根据需要访问的类抽象出一个接口Item,定义accept方法,然后将访问者抽象成接口Vistor,定义visit方法,overload多种版本,可访问类实现Item,访问类实现Vistor中的不同访问方法。

public interface ItemElement { 
    public int accept(ShoppingCartVisitor visitor);
}
/* Concrete element */ 
public class Book implements ItemElement{ 
    private double price; 
    ... 
    int accept(ShoppingCartVisitor visitor) { 
        visitor.visit(this);
    }
} 
public class Fruit implements ItemElement{ 
    private double weight; 
    ... 
    int accept(ShoppingCartVisitor visitor) { 
        visitor.visit(this);
    }
}
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;
    }
}

        client:

List<ItemElement>list = new ArrayList<>();
list.add(new Book(20 , "12"));
list.add(new Fruit(5 , 5 , "apple"));
ShoppingCartVisitor visitor = new ShoppingCartVisitorImpl();
int sum = 0;
for(ItemElement item : list){
    sum += item.accept(visitor);
    return sum;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值