设计模式三

本文介绍了结构型设计模式,包括适配器、桥接、组合、装饰和外观模式。详细阐述了各模式的意图,给出了类图和实现代码示例,如适配器将火鸡叫声适配成鸭子叫声,桥接分离遥控器和电视实现等,还提及了装饰和外观模式的设计原则。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

四、结构型

1. 适配器(Adapter)

Intent

把一个类接口转换成另一个用户需要的接口。

Implementation

鸭子(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 WildTurkey implements Turkey {

    @Override

    public void gobble() {

        System.out.println("gobble!");

    }

}

 

public class Client {

    public static void main(String[] args) {

        Turkey turkey = new WildTurkey();

        Duck duck = new TurkeyAdapter(turkey);

        duck.quack();

    }

}

 

2. 桥接(Bridge)

Intent

将抽象与实现分离开来,使它们可以独立变化。

Class Diagram

  • Abstraction:定义抽象类的接口
  • Implementor:定义实现类接口

Implementation

RemoteControl 表示遥控器,指代 Abstraction。

TV 表示电视,指代 Implementor。

桥接模式将遥控器和电视分离开来,从而可以独立改变遥控器或者电视的实现。

public abstract class TV {

    public abstract void on();

 

    public abstract void off();

 

    public abstract void tuneChannel();

}

 

public class Sony extends TV {

    @Override

    public void on() {

        System.out.println("Sony.on()");

    }

 

    @Override

    public void off() {

        System.out.println("Sony.off()");

    }

 

    @Override

    public void tuneChannel() {

        System.out.println("Sony.tuneChannel()");

    }

}

 

public class RCA extends TV {

    @Override

    public void on() {

        System.out.println("RCA.on()");

    }

 

    @Override

    public void off() {

        System.out.println("RCA.off()");

    }

 

    @Override

    public void tuneChannel() {

        System.out.println("RCA.tuneChannel()");

    }

}

 

public abstract class RemoteControl {

    protected TV tv;

 

    public RemoteControl(TV tv) {

        this.tv = tv;

    }

 

    public abstract void on();

 

    public abstract void off();

 

    public abstract void tuneChannel();

}

 

public class ConcreteRemoteControl1 extends RemoteControl {

    public ConcreteRemoteControl1(TV tv) {

        super(tv);

    }

 

    @Override

    public void on() {

        System.out.println("ConcreteRemoteControl1.on()");

        tv.on();

    }

 

    @Override

    public void off() {

        System.out.println("ConcreteRemoteControl1.off()");

        tv.off();

    }

 

    @Override

    public void tuneChannel() {

        System.out.println("ConcreteRemoteControl1.tuneChannel()");

        tv.tuneChannel();

    }

}

 

public class ConcreteRemoteControl2 extends RemoteControl {

    public ConcreteRemoteControl2(TV tv) {

        super(tv);

    }

 

    @Override

    public void on() {

        System.out.println("ConcreteRemoteControl2.on()");

        tv.on();

    }

 

    @Override

    public void off() {

        System.out.println("ConcreteRemoteControl2.off()");

        tv.off();

    }

 

    @Override

    public void tuneChannel() {

        System.out.println("ConcreteRemoteControl2.tuneChannel()");

        tv.tuneChannel();

    }

}

 

public class Client {

    public static void main(String[] args) {

        RemoteControl remoteControl1 = new ConcreteRemoteControl1(new RCA());

        remoteControl1.on();

        remoteControl1.off();

        remoteControl1.tuneChannel();

        RemoteControl remoteControl2 = new ConcreteRemoteControl2(new Sony());

         remoteControl2.on();

         remoteControl2.off();

         remoteControl2.tuneChannel();

    }

}

 

3. 组合(Composite)

Intent

将对象组合成树形结构来表示“整体/部分”层次关系,允许用户以相同的方式处理单独对象和组合对象。

Class Diagram

组件(Component)类是组合类(Composite)和叶子类(Leaf)的父类,可以把组合类看成是树的中间节点。

组合对象拥有一个或者多个组件对象,因此组合对象的操作可以委托给组件对象去处理,而组件对象可以是另一个组合对象或者叶子对象。

Implementation

public abstract class Component {

    protected String name;

 

    public Component(String name) {

        this.name = name;

    }

 

    public void print() {

        print(0);

    }

 

    abstract void print(int level);

 

    abstract public void add(Component component);

 

    abstract public void remove(Component component);

}

 

public class Composite extends Component {

 

    private List<Component> child;

 

    public Composite(String name) {

        super(name);

        child = new ArrayList<>();

    }

 

    @Override

    void print(int level) {

        for (int i = 0; i < level; i++) {

            System.out.print("--");

        }

        System.out.println("Composite:" + name);

        for (Component component : child) {

            component.print(level + 1);

        }

    }

 

    @Override

    public void add(Component component) {

        child.add(component);

    }

 

    @Override

    public void remove(Component component) {

        child.remove(component);

    }

}

 

public class Leaf extends Component {

    public Leaf(String name) {

        super(name);

    }

 

    @Override

    void print(int level) {

        for (int i = 0; i < level; i++) {

            System.out.print("--");

        }

        System.out.println("left:" + name);

    }

 

    @Override

    public void add(Component component) {

        throw new UnsupportedOperationException(); // 牺牲透明性换取单一职责原则,这样就不用考虑是叶子节点还是组合节点

    }

 

    @Override

    public void remove(Component component) {

        throw new UnsupportedOperationException();

    }

}

 

public class Client {

    public static void main(String[] args) {

        Composite root = new Composite("root");

        Component node1 = new Leaf("1");

        Component node2 = new Composite("2");

        Component node3 = new Leaf("3");

        root.add(node1);

        root.add(node2);

        root.add(node3);

        Component node21 = new Leaf("21");

        Component node22 = new Composite("22");

        node2.add(node21);

        node2.add(node22);

        Component node221 = new Leaf("221");

        node22.add(node221);

        root.print();

    }

}

 

Composite:root

--left:1

--Composite:2

----left:21

----Composite:22

------left:221

--left:3

4. 装饰(Decorator)

Intent

为对象动态添加功能。

Class Diagram

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

Implementation

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

下图表示在 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

 

设计原则

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

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

5. 外观(Facade)

Intent

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

Implementation

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

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();

    }

}

设计原则

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值