软件构造-5.2面向可维护性的设计模式

Creational patterns

工厂方法模式(Factory Method pattern)

工厂方法模式也称为虚拟构造器,创建实例时不使用new方法,而是通过使用接口的方式,让客户端与返回具体实例之间解耦合。它的具体描述是:当client不知道/不确定要创建哪个具体类的实例,或者想在client代码中指明要具体创建的实例时,用工厂方法。 定义一个用于创建对象的接口,让该接口的子类型来决定实例化哪一个类,从而使一个类的实例化延迟到其子类。它有两种实现。

  • 设计多个工厂方法
    如果设计多个具体的实现类,都继承自同一个顶层接口,在这个子类中实现它的不一致的功能,将相同的功能放在顶层接口中实现。那么这样的实现方式使得客户端与具体的实现相关联,知道具体的方法。而采用工厂方法,可以在接口中定义get方法获得实例,通过继承父类对子类进行实现,返回具体的实例。使用 “工厂方法”来创建实例,得到实例的类型是抽象接口不是具体类,这样在需要增加类型时更符合OCP原则。
  • 设计一个工厂方法
    在设计工厂方法时根据输入的类型来决定返回哪一种具体的实例。这种实现方式只需要设计一个工厂方法,将具体的类型都用一个case或者if-else语句进行判断。
    谈到工厂方法时,有一个与之功能相似的方法,称为静态工厂方法。静态工厂方法能够在ADT的内部直接实现,也可以构造单独的工厂。静态工厂方法能够具有指定名称,而不是仅仅new进行指定。并且静态工厂方法能够返回原来返回类型的任意子类型。

抽象工厂模式(Abstract Factory Pattern)

抽象工厂模式提供了接口用来创建一组相关联的对象,但是这个实现并未指明具体的实现类型。相当于将所有的功能进行了一个组合,每个不同的类需要完成的功能进行打包,而每个功能的具体的实现却并未包含,对象的实例创建放在了使用具体产品时。这个设计模式通过下面这个图形能够较为容易理解:
抽象工厂方法示意图
Abstract Factory 创建的不是一个完整产品,而是“产品族”(遵循固定搭配规则的多类产品的实例),得到的结果是:多个不同产品的object,各产品创建过程对client可见,但“搭配”不能改变。直接用factory method,client可能不知道搭配而用错工厂。

Structural patterns

代理模式(Proxy pattern)

代理模式的使用主要是因为在具体的应用当中,某些对象的信息不希望直接被客户端所访问到,因此设置了代理,在具体的对象隐秘信息间和具体的客户端之间设置防火墙。代理分为3种不同的方式,根据不同的实现需要采用不同的方法。

  • 远程代理
    远程代理是指为一个对象在不同的地址空间提供局部代表,本质上就是缓存机制。如果这个访问过程中,信息不会经常变化,那么远程代理能够很好提升性能,提升访问的速度。
  • 虚拟代理
    虚拟代理是根据实际的需要创建开销很大的对象,如果这个对象不会被经常访问到的话,我们使用虚拟代理就能够延迟创建,很大程度上能够提升程序的性能和访问速度。
  • 保护代理
    保护代理顾名思义就是为对象提供一种保护的机制。通过创建代理,不直接对实际对象进行访问,代理通过设置委托的方式对实际的对象进行访问,达到保护的目的,就是保护代理。

Behavioral patterns

观察者模式(Observer pattern)

观察者模式是为了保护状态的一致性,即有很多个对象依赖于某一个对象,但这个对象的状态或者信息发生改变的时候,就需要通过观察者模式对其他的对象进行通知。观察者模式是一种“发布-订阅”的形式,发布方发生了变化,通知订阅方,不同的订阅方根据具体的操作判断自身应该做什么操作。订阅方需要在发布方进行注册,发布方与订阅方之间通过接口进行分离。
抽象的subject需要维护一个订阅者列表,抽象的observer需要定义update的协议,即在得知发布方发生变化之后,自身做什么处理。具体的subject需要维护数据,修改之后通知订阅方,而具体的observer得到通知之后,需要修改自身的状态。
下面是一个具体的例子:

public class Subject{
    private List<Observer> observers = new ArrayList<Observer>();
    private int state;
    public int getState() {
        return state;
    }
    public void setState(int state) { 
        this.state = state; 
        notifyAllObservers();
    }
    public void attach(Observer observer){
        observers.add(observer);
    }
    private void notifyAllObservers(){
        for (Observer observer : observers) { 
            observer.update();
        }
    }
}
public abstract class Observer {
    protected Subject subject; 
    public abstract void update();
}
public class BinaryObserver extends Observer{
    public BinaryObserver(Subject subject){ 
        this.subject = subject; 
        this.subject.attach(this);
    }
    @Override
    public void update(){
        System.out.println( "Binary String: " +
Integer.toBinaryString( subject.getState() ) );
    }
}

观察者模式有3种变体,可以在发生变化时推送通知、推送通知和数据、拉取数据。观察者模式使得主体和观察者之间松耦合,主体不需要关注观察者,并且可以动态增加、删除观察者。同时观察者的行为也不受到主体的控制。实现过程中,主体需要存储观察者列表,同时可以在观察者中的update函数中增加参数来观察多个主体。同时可以设计触发机制。

访问者模式(Visitor pattern)

访问者模式的本质就是将数据和作用在数据上的操作分离开来,可能某些数据可以根据不同的操作进行处理,因此可以为ADT预留一个将来可以拓展功能的接入点,外部可以通过委托的方式接入到ADT中。下面以一个例子来进行展示:

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

在具体的实现中将数据和操作在运行时动态绑定,操作可以灵活更改,不需要更改visit的类。

Summary

以上5种是常用的面向可维护性的构造过程中的设计模式,分为了创建层面、结构层面和行为层面。创建层面主要有Factory methodAbstract factory,在结构层面有Porxy,在行为层面有ObserverVisitor

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值