上次介绍了一些软件构造中的设计模式,那其实,并没有介绍完,那些模式是面向复用性变成所需要的设计模式,而此篇中介绍的就不再是面向复用性了,而是面向可维护性编程的设计模式。
工厂方法模式
这也是在我们最开始做实验的遇到的一种“方法”,当时没有注意到这种模式,只是在老师介绍的时候说出:运用静态工厂方法,可以隐藏某种对象的构造,一防止表示泄露,例如:
public static <R> TrainSchedule<R> newPlanningEntryOfTrainSchedule(Location location, TimeSlot timeSlot,
String planningEntryNumber, String planningEntryDate) {
return new TrainSchedule<R>(location, timeSlot, planningEntryNumber, planningEntryDate);
}
这在接口中定义的静态工厂方法可以创造出一个TrainSchedule的对象,但是客户端却不知道这个对象是什么样的,他只知道通过这种方法他能够获得一个他所需要的对象,这就使避免了程序将某些信息暴露给客户端的危险现象。
当然,除此之外,我们也在其他地方用到过工厂方法,比如:
Collections.unmodifiableList(List);
这也是一种工厂方法的应用。
抽象工厂模式
如果理解了上面的工厂方法模式后,那么这种模式就很好理解了。上面的模式和抽象工厂模式的差异就是1和多的差异:
它将考虑多种对象的创建,用同一个具体工厂所生产的位于不同的一组对象。
这也可以看作为工厂方法的固定形式的叠加。
代理模式
在有些情况下,一个人不能或者不想直接访问另一个对象,这时需要找一个中介帮忙完成某项任务,这个中介就是代理对象。例如,生活中,有的人购买火车票不一定要去火车站买,可以通过 12306 网站或者去火车票代售点买。
所以在设计软件的过程中,使用代理模式的例子也很多,例如,要访问的远程对象比较大,其下载要花很多时间,如果有一个代理对象取缔这个步骤,那么就能提高效率。
这也是通过delegation完成的。
interface findobject
{
void find();
}
class RealSubject implements findobject
{
public void find()
{
System.out.println("找到一个大物件");
}
}
class Proxy implements findobject
{
private RealSubject realSubject;
public void find()
{
if (realSubject==null)
{
realSubject=new RealSubject();
}
prefind();
realSubject.find();//delegation
postfind();
}
public void prefind()
{
System.out.println("找之前的处理。");
}
public void postfind()
{
System.out.println("找之后的处理。");
}
}
public class ProxyTest
{
public static void main(String[] args)
{
Proxy proxy=new Proxy();
proxy.find();
}
}
结果:
观察者模式
这个模式生动的展示了现实社会中粉丝和偶像的关系:有一个偶像,他有着一堆认证过的粉丝,每个粉丝都在时时刻刻地关注着偶像的一举一动。
其中的关系如下图:
这也使用delegation来实现的,值得注意的一点是:粉丝在偶像中注册的时候是让偶像把自己注册在偶像的“粉丝名单”中,这是一种反向的delegation。
访问者模式
在现实生活中,有些对象的集合之中中存在多种不同的元素,且每种元素也存在多种不同的访问者和处理方式。例如,公园中存在多个景点,也存在多个游客,不同的游客对同一个景点的评价可能不同;比如,对与一部电影,其中有着许多演员,观众对每个演员的评价也不同。这时就需要区分每个人对应的不同的对象,。
在软件设计的时候,也是如此,访问者模式能把方法从数据结构中分离出来,并可以根据需要增加新的处理方法,且不用修改原来的程序代码与数据结构,这提高了程序的扩展性和灵活性。
实例:
interface Visitor
{
//两种不同的实现
void visit(ConcreteElementA element);
void visit(ConcreteElementB element);
}
class VisitorA implements Visitor
{
public void visit(ConcreteElementA element)
{
System.out.println("A访问"+element.operationA());
}
public void visit(ConcreteElementB element)
{
System.out.println("A访问"+element.operationB());
}
}
class VisitorB implements Visitor
{
public void visit(ConcreteElementA element)
{
System.out.println("B访问"+element.operationA());
}
public void visit(ConcreteElementB element)
{
System.out.println("B访问"+element.operationB());
}
}
interface Element
{
void accept(Visitor visitor);
}
class ConcreteElementA implements Element
{
public void accept(Visitor visitor)
{
visitor.visit(this);
}
public String operationA()
{
return "A的操作。";
}
}
class ConcreteElementB implements Element
{
public void accept(Visitor visitor)
{
visitor.visit(this);
}
public String operationB()
{
return "B的操作。";
}
}
class ObjectStructure
{
private List<Element> list=new ArrayList<Element>();
public void accept(Visitor visitor)
{
Iterator<Element> i=list.iterator();
while(i.hasNext())
{
((Element) i.next()).accept(visitor);
}
}
public void add(Element element)
{
list.add(element);
}
}
public class VisitorPattern
{
public static void main(String[] args)
{
ObjectStructure os=new ObjectStructure();
os.add(new ConcreteElementA());
os.add(new ConcreteElementB());
Visitor visitor=new VisitorA();
os.accept(visitor);
System.out.println();
visitor=new VisitorB();
os.accept(visitor);
}
}
状态模式
这种模式顾名思义:表示状态的。在我们学习形式语言和自动机这门课的时候,我们了解了状态这个概念,它描述了自动机在接受语言的时候某一时刻自动机的性能。
在用软件实现需要状态这个概念的设计的时候,我们就可以用这个模式,将表示状态这个功能外包出去,让一个单独的类完成状态的表示。
这样,就将状态表示和及其相关操作与对象本身隔离开来,提升了效率。
备忘录模式
和状态模式类似,有些时候,我们也需要我们设计的程序具有备忘录的功能,这样,我们就可以完成程序的版本转换等功能。
如果直接在程序中设计对象的部分添加方法显然是不符合我们的设计思想,我们需要用一个类单独地实现这个功能,也就是外包出去。这绝对是离不开delegation的。
例如:
class Memento
{
private String state;
public Memento(String state)
{
this.state=state;
}
public void setState(String state)
{
this.state=state;
}
public String getState()
{
return state;
}
}
//备忘录的一页
class Originator
{
private String state;
public void setState(String state)
{
this.state=state;
}
public String getState()
{
return state;
}
public Memento createMemento()
{
return new Memento(state);
}
public void restoreMemento(Memento m)
{
this.setState(m.getState());
}
}
//备忘录管理者
class Caretaker
{
private Memento memento;
public void setMemento(Memento m)
{
memento=m;
}
public Memento getMemento()
{
return memento;
}
}
public class MementoTest
{
public static void main(String[] args)
{
Originator or=new Originator();
Caretaker cr=new Caretaker();
or.setState("Running");
System.out.println("初始的状态:"+or.getState());
cr.setMemento(or.createMemento());
or.setState("Pausing");
System.out.println("修改为新的状态:"+or.getState());
or.restoreMemento(cr.getMemento());
System.out.println("恢复后状态:"+or.getState());
}
}
结果:
这样,这一门课中学过的设计模式就回顾的差不多了,不过也只是简单回顾而已,在实际的应用中,可能会比这中单独编写的情况复杂得多!