针对可复用性的设计模式:
结构
(1)适配器模式:
client想要调用LegacyRectangle,但是他们的传入参数不一致,我们需要增加一个适配器类Rectangle,这个适配器类实现了Shape接口,所以client直接委托给shape接口(实际上是调用适配器类)Shape shape = new Rectangle(),Rectangle里面进行了一些操作,使得传入的参数能委托给LegacyRectangle()实现。
(2)装饰器模式
client想要在原有stack上增加一些功能,于是他首先实现了stack接口为ArrayStack,然后为了扩充stack的功能,又设置了一个抽象装饰类,这个抽象装饰类实现了stack并且有将其作为了自己的成员变量,即可以将外部传入的stack具体实现类传进抽象装饰类中,这样就将基本的stack功能委托给了原来的ArrayStack类,而具体装饰类继承了抽象装饰类,在进行push操作时不仅采用super调用父类的push方法(实际上是调用了被委托类arraystack),而且还增加了新的特性。这样调用的时候
Stack s = new ArrayStack();
Stack t = new UndoStack(new ArrayStack());
实际上并没有出现抽象装饰类,只是创建了一个具体实现类,并把它传给具体装饰类。
这里还有一个问题,就是这里的抽象装饰类看似实现了所有父类的方法,实际上他重复调用了父类的方法,因此相当于没有真正实现。当然,这里也可以不实现,全部由具体的装饰器子类实现。
(3)外观模式
client调用一个封装类,这个类里面可以设置一个静态函数,根据传入的参数调用不同其他类的方法
行为
(1)策略模式
在商店付钱,可以创建将付款委托给一个接口实现,接口有多种实现方式,具体client调用时,可以在商店的构造函数里面确定传入的是哪个接口
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"));
(2)模板模式
就是抽象类里面一些未实现的方法让子类(可以是多个不同的)实现。注意抽象类里面的模板方法要加final,防止子类重写。
(3)迭代器模式
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(); } } }
针对可维护性的设计模式
创造
(1)工厂模式
有一个日志接口,有系统日志和文件日志两种实现方式。我们可以创建一个工厂方法接口,这个接口TraceFactory也有两种实现方式,每种对应返回一个日志。
client调用时只需: Trace log1 = new SystemTraceFactory().getTrace();
当然,也可以对TraceFactory只有一种实现方式,即
public class Factory implements TraceFactory { public getTrace(String type) { if(type.equals("file" ) return new FileTrace(); else if (type.equals("system") return new SystemTrace(); } }
这样就可以根据传入的参数选择创造哪种日志了。
也可以采用静态工厂方法,直接创建工厂类,不需要创建接口,工厂类里面有静态工厂方法,无需实例化工厂类。
(2)抽象工厂模式
工厂的工厂
针对两种不同的部件窗户和门板,每种分别有两种规格:大、小。为了创造一个产品族,我们设置一个抽象工厂接口,该接口有两个子类,每个子类有两个工厂方法,分别是create大窗户大门板,create小窗户小门板。此外我们还有一个工厂生成器类,根据传入的工厂参数(工厂1或工厂2)调用相应的生产方法。
client只需要new一个具体的抽象工厂传给工厂生成类即可。
结构
(1)代理模式
本来client可以直接调用真实对象,但是为了某些原因,我们把真实对象的方法剥离出来设置为一个接口,然后用真实和代理对象分别实现,其中代理对象实现的时候实际上是将该对象委托给真实对象实现。
行为
(1)观察者模式
偶像接口的状态改变委托给粉丝实现更新,粉丝接口的实现里更新可改变状态,粉丝创建之后委托偶像实现attach。
(2)访问者模式
实现某些方法时委托给访问者,访问者可以有不同的实现,从而可以切换访问方式。