重学设计模式(五)—— 装饰器、适配器、门面和代理

Decorator装饰器模式

装饰模式指的是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。

java IO 流是装饰模式一个典型的应用场景。

这里写图片描述

举个生活中的例子,饮品店的饮料价格由原料(咖啡、茶……)价格和配料(糖、奶泡……)价格组成,我们是计算价格的呢?如果为每一种组合创建一个类,显然不现实。但是如果我们把每一种饮品看作是配料对原料的修饰,那就简单多了,参考上述类图,我么可以新建Beverage类,这是饮料的基类,提供一个抽象方法用于计算饮料价格:
Beverage.java

public abstract class Beverage {
    String description = "Unknown Beverage";

    public String getDescription(){
        return description;
    }
    public abstract double cost();
}

在此基础上我们创建两个具体的原料类型Espresso和HouseBlend:
Espresso.java

public class Espresso extends Beverage {
    public Espresso(){
        this.description = "Espresso";
    }
    public double cost() {
        return 1.99;
    }
}

HouseBlend.java

public class HouseBlend extends Beverage{
    public HouseBlend(){
        this.description = "House Blend Coffee";
    }
    public double cost() {
        return 0.89;
    }
}

再来创建修饰类的基类Decorator和具体类Mocha:

Decorator.java

public abstract class Decorator extends Beverage {
    public abstract String getDescription();
}

Mocha.java

public class Mocha extends Decorator{
    private Beverage beverage;

    public Mocha(Beverage beverage) {
        this.beverage = beverage;
    }

    public String getDescription() {
        return beverage.getDescription() + ", Mocha";
    }

    public double cost() {
        return 0.2 + this.beverage.cost();
    }
}

如果我们想要一杯HouseBlend配加一分Mocha,一杯Espresso配加两份Mocha,就可以如下实现:

public class DecoratorTest {
    public static void main(String[] args) {
        //创建一个HouseBlend对象
        Beverage beverage = new HouseBlend();
        //用Mocha来修饰上述HouseBlend对象
        Beverage beverage1 = new Mocha(beverage);

        System.out.println(beverage1.getDescription() + " $" + beverage1.cost());

        System.out.println("=====================================");

        //创建一个Espresso对象
        beverage = new Espresso();
        //用2份Mocha来修饰上述HouseBlend对象
        Beverage beverage2 = new Mocha(beverage);
        beverage2 = new Mocha(beverage2);

        System.out.println(beverage2.getDescription() + " $" + beverage2.cost());
    }
}

运行结果:
这里写图片描述

Adaptor适配器模式

将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。——Gang of Four
这里写图片描述

我们生活中电子产品的工作电压一般都在36V以下,但是家里都是220V的交流电,这个时候便有了电源适配器这种东西。范围再广一点,大陆和香港地区的三相插座不一样,一般商家向大陆顾客出售产品的时候会额外提供一个插座的转换口。

生活中适配器的例子比比皆是,放到程序设计中来,当一个类接口不是客户想要的那种,我们便可以通过适配器方式转换该接口来满足需求。
Adaptee.java

public interface Adaptee {
    //需要被适配的类,目标接口
    void adaptedOperation();
}

ConcreteAdaptee.java


public class ConcreteAdaptee implements Adaptee {
    public void adaptedOperation() {
        System.out.println("this is a concrete adaptee!");
    }
}

Adaptor.java

public interface Adaptor {
    //适配类,即客户希望访问的接口
    void doSomething();
}

ConcreteAdaptor.java

public class ConcreteAdaptor implements Adaptor {
    private Adaptee adaptee;

    public ConcreteAdaptor(Adaptee adaptee) {
        this.adaptee = adaptee;
    }

    public void doSomething() {
        this.adaptee.adaptedOperation();
    }
}

当我们希望通过访问适配方法实现对目标方法的访问,便可以如下实现:

public class AdaptorTest {
    public static void main(String[] args) {
        //目标接口
        Adaptee adaptee = new ConcreteAdaptee();
        //适配目标接口
        Adaptor adaptor = new ConcreteAdaptor(adaptee);
        //通过访问适配方法实现访问目标方法
        adaptor.doSomething();
    }
}

运行结果:
这里写图片描述

Facade门面模式

外观模式通过封装许多对象,以简化它们的接口,此模式定义了一个高层的接口,这个接口使得这一子系统更加容易使用。

最少知识原则是门面模式遵循的一个设计原则。

最少知识原则:只和你的密友谈话。

这个原则希望我们在设计中,不要让太多的类耦合在一起,免得修改系统的一部分,会影响到其他部分。

Proxy代理模式

详见博主之前的文章《动态代理》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值