设计模式 - 门面模式/适配器模式/装饰器模式

8. 门面/外观模式(Facade)

目的

提供了一个统一的接口,用来访问子系统中的一群接口,从而让子系统更容易使用。

类图


实现

观看电影需要操作很多电器,使用门面模式实现一键看电影功能。

public class SubSystem {
    public void turnOnTV() {
        System.out.println("turnOnTV()");
    }

    public void setCD(String cd) {
        System.out.println("setCD( " + cd + " )");
    }

    public void startWatching(){
        System.out.println("startWatching()");
    }
}
public class Facade {
    private SubSystem subSystem = new SubSystem();

    public void watchMovie() {
        subSystem.turnOnTV();
        subSystem.setCD("a movie");
        subSystem.startWatching();
    }
}
public class Client {
    public static void main(String[] args) {
        Facade facade = new Facade();
        facade.watchMovie();
    }
}

设计原则

最少知识原则:只和你的密友谈话。也就是说客户对象所需要交互的对象应当尽可能少。

应用场景

  • 当需要使用复杂子系统的有限但直接的接口时
  • 当想要将子系统组织成层时

优点

简化客户端的使用

9. 适配器(Adapter)

模式定义

将一个类的接口转换成客户希望的另一个接口,Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

类图


实现

场景一:对象适配器模式【组合】

220v到5v的变压器

public class AdapyerTest1 {
    public static void main(String[] args){
      new adaptee = new Adaptee();
      Target target = new Adapter(adaptee);
      target.output5v();
    }
}
class Adaptee {
  public int output200v(){
    return 220;
  }
}
interface Target{
  int output5v();
}
class Adapter implements Target{
  Adaptee adaptee;
  public Adapter(Adaptee adaptee){
    this.adaptee=adaptee;
  }
  @Override
  public int output5v(){
    int i=adaptee.output220v();
    //模拟一系列复杂的转换工作
    System.out.println(String.format("原始点呀:%d v -> 输出电压:%d v ",i,5))return 5}
}
场景二:类的适配器模式【继承】

220v到5v的变压器

public class AdapyerTest1 {
    public static void main(String[] args){
      Adapter adapter = new Adapter();
      adapter.output5v();
    }
}
class Adaptee {
  public int output200v(){
    return 220;
  }
}
interface Target{
  int output5v();
}
class Adapter extends Adaptee implements Target{
  @Override
  public int output5v(){
    int i= this.output220v();
    //模拟一系列复杂的转换工作
    System.out.println(String.format("原始点呀:%d v -> 输出电压:%d v ",i,5))return 5}
}

类的适配器的缺点:对代码有污染,我们只需要5v的电压,但是也可以输出220v的电压了。

场景三:对象适配器模式

鸭子(Duck)和火鸡(Turkey)拥有不同的叫声,Duck 的叫声调用 quack() 方法,而 Turkey 调用 gobble() 方法。

要求将 Turkey 的 gobble() 方法适配成 Duck 的 quack() 方法,从而让火鸡冒充鸭子!

public interface Duck {
    void quack();
}
public interface Turkey {
    void gobble();
}
public class WildTurkey implements Turkey {
    @Override
    public void gobble() {
        System.out.println("gobble!");
    }
}
public class TurkeyAdapter implements Duck {
    Turkey turkey;

    public TurkeyAdapter(Turkey turkey) {
        this.turkey = turkey;
    }

    @Override
    public void quack() {
        turkey.gobble();
    }
}
public class Client {
    public static void main(String[] args) {
        Turkey turkey = new WildTurkey();
        Duck duck = new TurkeyAdapter(turkey);
        duck.quack();
    }
}

应用场景

  • 当希望使用某些现有类,但其借口与你的其他代码不兼容时
  • 当希望重用几个现有的子类,这些子类缺少一些不能添加到超类中的公共功能时

优点

  • 符合单一职责原则
  • 符合开闭原则

10. 装饰者(Decorator)

目的

为对象动态添加功能。

模式定义

在不改变原有对象的基础上,将功能附加到对象上。

类图

装饰者(Decorator)和具体组件(ConcreteComponent)都继承自组件(Component),具体组件的方法实现不需要依赖于其它对象,而装饰者组合了一个组件,这样它可以装饰其它装饰者或者具体组件。所谓装饰,就是把这个装饰者套在被装饰者之上,从而动态扩展被装饰者的功能。装饰者的方法有一部分是自己的,这属于它的功能,然后调用被装饰者的方法实现,从而也保留了被装饰者的功能。可以看到,具体组件应当是装饰层次的最低层,因为只有具体组件的方法实现不需要依赖于其它对象。


实现

场景一

相机具备拍照功能,添加美颜等其他功能。

public class DecoratorTest {
	public statuc void main(String[] args){
		Component component = new ConreteDecorator(new ConcreteComponent() );
		component.opeartion();
		
		Component component = new ConreteDecorator2(new ConreteDecorator(new ConcreteComponent() ) );
		component.opeartion();
	}
}

interface Component {
	void operation();
}
class ConcreteComponent implements Component{
	@Override 
	public void operation(){
		system.out.println("拍照.");
	}
}

//装饰者抽象类
abstract class Decorator implements Component{
	Component component;
	public Decorator(Component component){
		this.component = component;
	}
}

//装饰者具体实现:添加美颜效果
class ConreteDecorator extends Decorator{
	public ConreteDecorator(Component component){
		super(component);
	}
	@Override
	public void operation(){
		system.out.println("添加美颜.");
		component.operation();
	}
}

//装饰者具体实现:添加滤镜效果
class ConreteDecorator2 extends Decorator{
	public ConreteDecorator2(Component component){
		super(component);
	}
	@Override
	public void operation(){
		system.out.println("添加滤镜.");
		omponent.operation();
	}
}

最后输出
在这里插入图片描述

场景二

设计不同种类的饮料,饮料可以添加配料,比如可以添加牛奶,并且支持动态添加新配料。每增加一种配料,该饮料的价格就会增加,要求计算一种饮料的价格。

下图表示在 DarkRoast 饮料上新增新添加 Mocha 配料,之后又添加了 Whip 配料。DarkRoast 被 Mocha 包裹,Mocha 又被 Whip 包裹。它们都继承自相同父类,都有 cost() 方法,外层类的 cost() 方法调用了内层类的 cost() 方法。


public interface Beverage {
    double cost();
}
public class DarkRoast implements Beverage {
    @Override
    public double cost() {
        return 1;
    }
}
public class HouseBlend implements Beverage {
    @Override
    public double cost() {
        return 1;
    }
}
public abstract class CondimentDecorator implements Beverage {
    protected Beverage beverage;
}
public class Milk extends CondimentDecorator {

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

    @Override
    public double cost() {
        return 1 + beverage.cost();
    }
}
public class Mocha extends CondimentDecorator {

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

    @Override
    public double cost() {
        return 1 + beverage.cost();
    }
}
public class Client {

    public static void main(String[] args) {
        Beverage beverage = new HouseBlend();
        beverage = new Mocha(beverage);
        beverage = new Milk(beverage);
        System.out.println(beverage.cost());
    }
}
3.0

设计原则

类应该对扩展开放,对修改关闭:也就是添加新功能时不需要修改代码。饮料可以动态添加新的配料,而不需要去修改饮料的代码。

不可能把所有的类设计成都满足这一原则,应当把该原则应用于最有可能发生改变的地方。

应用场景

  • 扩展一个类的功能或者给一个类添加附加职责

优点

  • 不改变原有对象的情况下给一个对象扩展功能
  • 使用不同的组合可以实现不同的效果
  • 符合开闭原则
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值