接口型设计模式

  • 适配器模式(Adapter)

    将没有耦合的两段程序通过适配器使它们相互协作

  • 外观模式(Facade)

    为防止程序变成混乱在一团的小块程序,将它们归类,引用一个外观角色来降低外部的使用复杂度

  • 合成模式(Composite)

    可嵌套的对象组合,更加方便的处理对象们的聚合关系

  • 桥接模式(Bridge)

    抽象与实现的分离,可自由组合,代替抽象与实现两个可变维度的多种变化

前言

接口类是一种约束,一个类(实现了该接口的类)的特征集,而这种特征集被java抽象的定义为接口,并允许它真实的独立存在,且将接口与实现分离,且每个类都能使用,也不限于某一个接口,而是一个类可以实现多个接口。这种约束可以让我更加清晰的阅读程序代码,当我们看到一个实现类后,我们迅速的知道该实现类会有那些动作,例如:老虎,在我们了解到老虎属于猫科动物时,首先下意识的明白它是有尖尖的爪子、细长的牙齿,但是猫科动物们具体怎么使用爪子和牙齿却没有限制。

接口其实也可以不带方法,此类型的接口被称之为标记型接口,例如Cloneable

/** Copyright (c) 1995, 2004, Oracle and/or its affiliates. All rights reserved.* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.*/package java.lang;/*** A class implements the <code>Cloneable</code> interface to* indicate to the {@link java.lang.Object#clone()} method that it* is legal for that method to make a* field-for-field copy of instances of that class.* <p>* Invoking Object's clone method on an instance that does not implement the* <code>Cloneable</code> interface results in the exception* <code>CloneNotSupportedException</code> being thrown.* <p>* By convention, classes that implement this interface should override* <tt>Object.clone</tt> (which is protected) with a public method.* See {@link java.lang.Object#clone()} for details on overriding this* method.* <p>* Note that this interface does <i>not</i> contain the <tt>clone</tt> method.* Therefore, it is not possible to clone an object merely by virtue of the* fact that it implements this interface.  Even if the clone method is invoked* reflectively, there is no guarantee that it will succeed.** @author  unascribed* @see     java.lang.CloneNotSupportedException* @see     java.lang.Object#clone()* @since   JDK1.0*/
public interface Cloneable {
}

许多设计模式都是使用了Java内建的这种特性。例如,适配器(Adapter)模式,通过使用一个接口类型来适配类的接口,从而达到想要的目的。若想运用好java基本的内建特性,就要从接口开始,确保自己掌握了Java特性的工作原理。

接口与抽象类

很多语言都不存在接口的这种结构,它们只有抽象类而没有接口,例如C++。由于Java接口与抽象类非常相似,如果不使用接口,也完全可以像C++那样使用抽象类,然而,作为一种独立的机构,接口在多层的应用程序开发过程中的地位举足轻重。

抽象类与接口的区别

  • 抽象类只能被单继承;接口可以被多实现(接口也可以继承接口,并且可以继承多个接口)

  • 抽象类可以用具体方法;接口的所有方法都是抽象方法

  • 抽象类可以声明字段和使用字段;接口则不能,但是可以创建静态默认修饰或者final默认修饰常量(在java1.5后,引进了enum,逐渐被enum所替代)

  • 抽象类的方法可以使public、protected、private或者默认的package;接口里的方法都是public

  • 抽象类可以定义构造函数;接口则不能

切记

不同于方法,方法可以默认public关键字修饰,但接口如果省略掉public,那么该接口只能在同级包下使用

注意,该接口是没有public关键字的

package org.learn.patterns.interfaces;interface InterfaceDemo {}

在不同的包下,我们无法使用这个接口

有时候,一些接口中的某些方法我们并不是都需要,但是Java接口的实现却是规范全部重写(override),为了在这一特性下灵活的使用接口,我们可以定义一些桩(stub),即可以提供一个空实现的接口实现类(注意这个类,不是接口),当我们再想用这些方法时,只需继承它的实现类即可,我们可以从实现类的方法中选择那些更有效的方法来实现,而忽略那些不关心的方法

原接口

我们假设猫科动物接口有这四类特征,我们如果要定义一个老虎子的实现类,目前我们只认为老虎会使用牙齿和爪子进行撕咬。其它的,例如舌头和尾巴,老虎很少使用,所以我们只需要实现useClaws()和useTooth()两个方法,但是Java的接口规范是必须要实现所有方法。

package org.learn.patterns.interfaces;public interface Felid {public void useClaws();public void useTooth();public void useTongue();public void useTail();
}

桩(stub)就很好的解决了这一点,它让接口变得像普通类一样,子类可以选择性的继承一些自己关注的方法。

package org.learn.patterns.implementss;import org.learn.patterns.interfaces.Felid;public class FelidStub implements Felid {@Overridepublic void useClaws() {}@Overridepublic void useTooth() {}@Overridepublic void useTongue() {}@Overridepublic void useTail() {}
}

资源类

​ 我们新建的老虎类并不用在实现猫科动物接口的所有方法,我们直接继承桩,然后选择自己需要的方法再重写。

package org.learn.patterns.implementss;public class Tiger extends FelidStub {@Overridepublic void useClaws() {System.out.println("老虎使用了一次爪子");}@Overridepublic void useTooth() {System.out.println("老虎使用了一次牙齿");}
}

适配器模式(Adapter)

适配器模式是指,把一个现有类的方法包装进另一个接口的实现类的方法里进行调用,使两个没有任何关系的类可以相互协作。适配器模式的中心思想还是让两段没有任何耦合代码可以通过适配器类进行相互协作,适配器模式可分为对象适配器类适配器两种。

概念角色

  • Target(目标抽象类或接口):抽象定义客户端所需要的接口,即暴露给客户端使用的接口,可以是接口,也可以是抽象类,也可以是具体类

  • Adapter(适配器):适配器类,具体的实现类,通过继承(或实现)Target并关联Adaptee类使二者进行联动。

  • Adaptee(被适配者):被适配者,已经存在的接口实现方案,一般情况都是一个具体类,但是需要进行适配。

类适配器

类适配器通常将已有的逻辑适配进程序中,这样即保留了原有代码,已达到了目的。如果我们不使用适配器模式,我们需要将被适配者的逻辑全部复制到目标抽象类(或接口)的实现中,这样重复造轮子实在有点小题大做。类适配器通常要满足里氏代换原则,才能完全适配使用。

Target

此接口为暴露给客户端的接口

package org.learn.patterns.interfaces.adapter_patterns;public interface Target {public void method1();
}

Adaptee

Adaptee类通常是真实开发的代码,通常会与原接口存在差异,所以需要适配

package org.learn.patterns.interfaces.adapter_patterns;public class AdapteE {public void adapteeMethod(){System.out.println("这是被适配者的方法");}
}

Adapter

Adapter的作用就是将AdapteE的逻辑适配进来

package org.learn.patterns.interfaces.adapter_patterns;public class Adapter extends AdapteE implements Target {@Overridepublic void method1() {adapteeMethod();}
}

Test

public static void main(String[] args) {Adapter adapter = new Adapter();adapter.method1();}

执行结果

对象适配器

很多时候需要适配的方法并非抽象,因此类适配器的方式就不奏效了。对象适配器弃用继承而使用委派(方法调用),这种方式虽然更加灵活,但是却也更加脆弱。

旧的车(target)

package org.learn.patterns.interfaces.adapter_patterns.object_adapter;public class OldCar {protected String carKay = "CarKay";private int tyre;private String frame;public OldCar(int tyre, String frame) {this.tyre = tyre;this.frame = frame;}public void run() {}public void stop() {}public int getTyre() {return tyre;}public String getFrame() {return frame;}}

新能源汽车(Adaptee)

package org.learn.patterns.interfaces.adapter_patterns.object_adapter;public class NewEnergyCar {private double electric;private int driver;public NewEnergyCar(double electric, int driver) {this.electric = electric;this.driver = driver;}public String startCar(String carKey){return "新能源汽车启动了";}public String breakCar(String carKey){return "新能源汽车停车了";}}

适配器类

package org.learn.patterns.interfaces.adapter_patterns.object_adapter;public class GoodCar extends OldCar {private NewEnergyCar newEnergyCar;public GoodCar(int tyre, String frame, NewEnergyCar newCar) {super(tyre, frame);newEnergyCar = newCar;}@Overridepublic void run() {System.out.println(getFrame() + getTyre() + "个轮胎的" + newEnergyCar.startCar(carKay));}@Overridepublic void stop() {System.out.println(getFrame() + getTyre() + "个轮胎的" + newEnergyCar.breakCar(carKay));}
}
缺点

对象适配器相较于类适配器有着非常大的风险

  • NewEnergyCar类的适配方法必须修饰为final,否则子类继承并重写该方法会带来较大的不稳定性

  • OldCar类并不是接口,且我们无法约束它的变化,可能会在运行时出现编译期无法检测到的问题

外观模式(Facade)

面向对象的最大的优势,在于它能够防止应用程序变成混乱纠缠在一团的多个小块程序。而外观模式通常把这一优势发挥得淋漓尽致,它通过引入一个外观角色来简化客户端子系统之间的交互,即为复杂的子系统提供统一的入口,降低客户端子系统的耦合性,尽可能地将可复用的模块组织在一起。

假设我们去购买了一杯奶茶,对于奶茶店而言,制作一杯奶茶通常分为加小料、加茶水、加糖、加冰块、搅拌、封口、打包,然而这些步骤通常已经被奶茶店所“封装”,站在我们的角度,我们只需要做的是买单然后喝奶茶就行,这个例子也就是现实生活的中的“外观模式”,我们点单的操作其实就相当于在使用外观类,而制作奶茶的这些“动作”就是奶茶的一些“子系统”,本质上我们其实还是在使用子系统,但是有了外观模式的介入后,我们可以更加轻便地使用这些子系统。从而也满足了面向对象编程系统的特性,即“不关心过程与实现,只关心结果”。

概念角色

  • **外观类(Facade):**外观类通常会暴露给客户端使用,外观类必须要了解子系统的职责和功能,通常情况下,外观类从客户端收到“命令”后,将“任务”拆分成各个职责委派给各个子系统。

  • **子系统(SubSystem):**子系统就是整个外观模式的真实“打工仔”,所有工作最终还是要靠子系统完成。子系统们其实感受不到外观类的存在,它们也可以被客户端直接调用,对于它们而言,外观类也仅仅客户端而已。

示例:家庭影院

这个例子是在网上抄的,但是,我只抄了它的代码例子,其它的东西一概不碰,因为我是实在想不到比家庭影院更合适的例子了,所以请原谅我的“借鉴”。

原文链接:https://blog.csdn.net/qq_45034708/article/details/114972361*/

子系统

播放器 保留原文链接,这是对作者的尊重

package org.learn.patterns.facede_patterns;public class Player {private static Player instance = new Player();private Player() {}public static Player getInstance() {return instance;}public void on() {System.out.println(" 播放器打开了 ");}public void off() {System.out.println(" 播放器关闭了 ");}public void play() {System.out.println(" 播放器播放中 ");}public void pause() {System.out.println(" 播放暂停 ");}/*————————————————版权声明:本文为CSDN博主「吾仄lo咚锵」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。原文链接:https://blog.csdn.net/qq_45034708/article/details/114972361*/
}

投影仪

package org.learn.patterns.facede_patterns;public class Projector {private static Projector instance = new Projector();private Projector() {}public static Projector getInstance() {return instance;}public void on() {System.out.println(" 投影仪打开了 ");}public void off() {System.out.println(" 投影仪关闭了 ");}public void focus() {System.out.println(" 投影仪聚焦 ");}public void zoom() {System.out.println(" 投影仪放大 ");}/*————————————————版权声明:本文为CSDN博主「吾仄lo咚锵」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。原文链接:https://blog.csdn.net/qq_45034708/article/details/114972361*/
}

屏幕

package org.learn.patterns.facede_patterns;public class Screen {private static Screen instance = new Screen();private Screen() {}public static Screen getInstance() {return instance;}public void up() {System.out.println(" 屏幕上升 ");}public void down() {System.out.println(" 屏幕下降 ");}/*————————————————版权声明:本文为CSDN博主「吾仄lo咚锵」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。原文链接:https://blog.csdn.net/qq_45034708/article/details/114972361*/
}

音响

package org.learn.patterns.facede_patterns;public class Stereo {private static Stereo instance = new Stereo();private Stereo() {}public static Stereo getInstance() {return instance;}public void on() {System.out.println(" 音响打开了 ");}public void off() {System.out.println(" 音响关闭了 ");}public void setVolume() {System.out.println(" 音响音量调节 ");}/*————————————————版权声明:本文为CSDN博主「吾仄lo咚锵」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。原文链接:https://blog.csdn.net/qq_45034708/article/details/114972361*/
}
外观类

家庭影院类

package org.learn.patterns.facede_patterns;public class FamilyCinema {private Player player;private Screen screen;private Projector projector;private Stereo stereo;public FamilyCinema() {this.player = Player.getInstance();this.screen = Screen.getInstance();this.projector = Projector.getInstance();this.stereo = Stereo.getInstance();}public void ready(){System.out.println("准备工作开始==========");screen.down();projector.on();stereo.on();player.on();stereo.setVolume();projector.on();projector.zoom();projector.focus();}public void start(){System.out.println("电影开始==========");player.play();}public void pause() {System.out.println("电影暂停==========");player.pause();}public void end(){System.out.println("电影播放完毕==========");player.off();stereo.off();screen.up();projector.off();}/*————————————————版权声明:本文为CSDN博主「吾仄lo咚锵」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。原文链接:https://blog.csdn.net/qq_45034708/article/details/114972361*/
}

合成模式(Composite)

合成模式,也称组合模式。合成模式是一组对象的组合,像是一把折扇,每个对象像是折扇的扇骨,折扇可以轻松合上与打开,因为它的扇骨都是同一大小且相同形状,合上以后成扑克牌状,从上面看就像是只有一张扑克牌一样。合成模式也是利用这一点,所以对象必须实现同一抽象,这样才能形成聚合关系,但是又优于扇子结构。扇子只有一个这个整体结构(扇子本身)才能算是“容器”,扇骨只能算是“节点”,扇骨无法在包含其它扇骨。而合成模式的"扇骨"却分为两种,一种是Composite(节点),俗称“树枝”,另一种是Leaf,俗称“叶子”,不同于普通节点“叶子”,“树枝”可以作为容器包含其它“叶子”与“树枝”,从而形成递归关系,可以处理更加复杂的组合关系。

概念角色

  • Component(抽象组件):“叶子”与“树枝”必须实现(或继承)的抽象类。该组件定义了管理子节点的抽象方法。
  • Leaf(叶子):“叶子”没有子节点,对于父类的管理管理子节点的方法,通常会以抛异常的方式处理。
  • Composite(树枝):“树枝”可以包含子节点,可以包含除Component以外所有的子节点。

示例:家族关系

现在我们把外公家的家庭成员用合成模式表示出来

抽象组件

​ 用抽象类是为了保留它固定的属性,例如:姓名,使它的任意一级子类都能轻松使用

package org.learn.patterns.composite_patterns;import java.util.ArrayList;
import java.util.List;public abstract class Kinship {//他们小孩protected List<Kinship> offspring = new ArrayList<>();//称呼,例如:大舅、大姨protected String name;public Kinship(String name) {this.name = name;}//声明是他的孩子,例如大表姐是大舅家的小孩public abstract void hisChild(Kinship people);//结婚,互相“连接”的配偶关系public abstract void marry(Kinship people);//子女离家出走,断开关系,类似删除方法public abstract void leave(Kinship people);//get方法public abstract Kinship getChild(int idx);//通知方法。相互转告public abstract void tell(String message);}

树枝

成年人(类),成年人可以拥有小孩,所以这是树枝类,为了更符合逻辑,我又多加了一个配偶对象

package org.learn.patterns.composite_patterns;import java.util.List;
import java.util.Objects;public class Adult extends Kinship {//配偶private Kinship spouse;public Adult(String name) {super(name);}@Overridepublic void hisChild(Kinship people) {offspring.add(people);if (Objects.nonNull(spouse)) {if (!spouse.offspring.contains(people)) {System.out.println(name + "与" + spouse.name + "的孩子是:" + people.name);spouse.hisChild(people);}}}@Overridepublic void marry(Kinship spouse) {if (Objects.nonNull(spouse)) {if (!spouse.equals(this.spouse)) {this.spouse = spouse;spouse.marry(this);}}}@Overridepublic void leave(Kinship people) {offspring.remove(people);}@Overridepublic Kinship getChild(int idx) {return offspring.get(idx);}@Overridepublic void tell(String message) {System.out.println(name + "家========");System.out.println(name + "已经下发消息:" + message);System.out.println(name + "已经收到消息:" + message);if (Objects.nonNull(this.spouse)) {System.out.println(this.spouse.name + "已经收到消息:" + message);}offspring.forEach(people -> people.tell(message));}
}

叶子

小孩(类),叶子节点,小孩没有小孩。

package org.learn.patterns.composite_patterns;public class Kid extends Kinship {public Kid(String name) {super(name);}@Overridepublic final void hisChild(Kinship people) {System.out.println("小孩不能生小孩");}@Overridepublic final void marry(Kinship people) {System.out.println("小孩不能结婚");}@Overridepublic final void leave(Kinship people) {System.out.println("小孩不能管别人离家出走");}@Overridepublic final Kinship getChild(int idx) {System.out.println("小孩没有小孩");return null;}@Overridepublic void tell(String message) {System.out.println(name + "已经收到消息:" + message);}
}

start

package org.learn.patterns.composite_patterns;public class Main {public static void main(String[] args) {//外公家====================================Kinship grandfather = new Adult("外公");Kinship djUncle = new Adult("大舅");Kinship dyAunt = new Adult("大姨");Kinship mom = new Adult("妈妈");Kinship xjUncle = new Adult("小舅");Kinship xyAunt = new Adult("小姨");//大舅家====================================Kinship djmAunt = new Adult("大舅妈");Kinship dbjFemaleCousin = new Kid("大表姐");Kinship xbjFemaleCousin = new Kid("小表姐");djUncle.marry((Adult) djmAunt);djUncle.hisChild(dbjFemaleCousin);djUncle.hisChild(xbjFemaleCousin);//大姨妈家====================================Kinship dyfUncle = new Adult("大姨夫");Kinship dbmFemaleCousin = new Kid("大表妹");Kinship xbmFemaleCousin = new Kid("小表妹");Kinship bdMaleCousin = new Kid("表弟");dyAunt.marry((Adult) dyfUncle);dyAunt.hisChild(dbmFemaleCousin);dyAunt.hisChild(xbmFemaleCousin);dyAunt.hisChild(bdMaleCousin);//妈妈家====================================Kinship dad = new Adult("爸爸");Kinship elderSister = new Kid("姐姐");Kinship youngerBrother = new Kid("弟弟");mom.marry((Adult) dad);mom.hisChild(elderSister);mom.hisChild(youngerBrother);//小舅家====================================Kinship xjmAunt = new Adult("小舅妈");Kinship bmFemaleCousin = new Kid("表妹");xjUncle.marry((Adult) xjmAunt);xjUncle.hisChild(bmFemaleCousin);//小姨妈家====================================Kinship xyfUncle = new Adult("小姨夫");Kinship femaleCousin = new Kid("表姐");Kinship xbdMaleCousin = new Kid("小表弟");xyAunt.marry((Adult) xyfUncle);xyAunt.hisChild(femaleCousin);xyAunt.hisChild(xbdMaleCousin);//============================================grandfather.hisChild(djUncle);grandfather.hisChild(dyAunt);grandfather.hisChild(mom);grandfather.hisChild(xyAunt);//外公发话了====================================grandfather.tell("过来吃饭");}
}

执行结果

桥接模式(Bridge)

将抽象与实现分离,使它们可以自由组合成多种形态,来代替抽象与实现两个可变维度的多种变化,这里的抽象是指一个对象的主要组成部分(例如玩具的样式,汽车、洋娃娃、积木),实现是指一个对象的次要组成部分(例如玩具的颜色,红色、蓝色、绿色),我个人把这其中的抽象理解主要抽象,把实现理解为另外一个次要抽象,而桥接模式就是分离出这两种抽象并降低它的耦合而又复用它们的子类形成多种组合从而代替抽象的多种变化。假设主次抽象不分离,那么我们要展示所有9个由不同颜色和种类组成的玩具就要定义9个该抽象的子类,如果再多出一种颜色与玩具种类,那么该抽象的子类又会增加到16个。

所以主次抽离分离可以很好的避免这一点,我们需要将它的颜色单独抽离成另外一个抽象(接口),然后将次要抽象的引用交给主要抽象封装,复用主次抽象的种类与颜色子类可组合成多种不一样的玩具,正是有了这两种抽象的分离才能防止组合数量有几何数增长。

概念角色

  • 抽象类:主要抽象,作为最后实现的主要属性,它一定得设计成抽象类,这样才能封装次要抽象让它的子类”桥接“

  • 具体类:主要抽象的拓展子类,因为父类封装了次要抽象,所以它可以直接调用次要抽象的方法

  • 次要抽象类:分离出来的次要抽象接口

  • 次要具体类:次要抽象接口的拓展子类

示例:玩具生产

抽象类:玩具

package org.learn.patterns.bridge_patterns;public abstract class Toys {protected Color color;//次要抽象对象的引用//增加构造方法使其子类必须有颜色public Toys(Color color) {this.color = color;}//制作玩具public abstract void make();//改变玩具颜色public void setColor( Color color){this.color=color;};
}

具体类:玩具种类-洋娃娃

package org.learn.patterns.bridge_patterns;public class Doll extends Toys {public Doll(Color color) {super(color);}@Overridepublic void make() {System.out.println("生产了一个洋娃娃");color.paint();}
}

次要抽象:颜色

package org.learn.patterns.bridge_patterns;public interface Color {//涂上颜色void paint();
}

次要具体类:颜色-红色

package org.learn.patterns.bridge_patterns;public class Red implements Color {@Overridepublic void paint() {System.out.println("涂上了红色");}
}

PS:其它颜色与种类就不写了

start

package org.learn.patterns.bridge_patterns;public class Main {public static void main(String[] args) {//红色汽车Toys car=new Car(new Red());car.make();//绿色洋娃娃Toys doll=new Doll(new Green());doll.make();//蓝色积木Toys bricks=new Bricks(new Blue());bricks.make();}
}

执行结果

示例拓展:三个及以上维度的桥接模式

我在浏览技术大牛的博客时,看见底下评论了这么一句话:“如果再加一个属性类是不是还得改主要抽象类?这么做是不是违背了开闭原则?跟直接写一个属性有什么区别呢?”。然而也有人说桥接模式只能适用两个维度的桥接,如果有三维度或以上那只能是使用别的设计模式了,为此我特别修改了一下,使上面的桥接模式能够适应三个及以上的属性。

主要抽象类:玩具

package org.learn.patterns.interfacial.bridge_patterns.hight_level;public abstract class Toys {//为了适应多个属性,次要抽象已经变成一个“属性工厂”protected AbstractAttrsFactory attributesFactory;public Toys(AbstractAttrsFactory attributesFactory) {this.attributesFactory = attributesFactory;}//制作玩具public abstract void make();//重新设置属性public void setAttributesFactory(AbstractAttrsFactory attributesFactory) {this.attributesFactory = attributesFactory;}
}

具体类:玩具种类-洋娃娃

package org.learn.patterns.interfacial.bridge_patterns.hight_level;public class Doll extends Toys {public Doll(AbstractAttrsFactory attributesFactory) {super(attributesFactory);}@Overridepublic void make() {System.out.println("生产了一个高级娃娃");//添加属性attributesFactory.transfer();}
}

次要抽象:抽象属性工厂

package org.learn.patterns.interfacial.bridge_patterns.hight_level;public abstract class AbstractAttrsFactory {//属性对象数组protected Attributes[] attributes;//使用可变参数作为传参可以使添加属性变灵活public AbstractAttrsFactory(Attributes... attributes) {this.attributes = attributes.clone();}//此方法统一调用所有属性对象的方法public abstract void transfer();
}

次要实体类:属性工厂

package org.learn.patterns.interfacial.bridge_patterns.hight_level;public class AttributesFactory extends AbstractAttrsFactory {public AttributesFactory(Attributes... attributes) {super(attributes);}@Overridepublic void transfer() {//循环遍历调用所以属性对象里的方法for (int i = 0; i < attributes.length; i++) {attributes[i].execute();}}
}

次要抽象:属性接口

package org.learn.patterns.interfacial.bridge_patterns.hight_level;public interface Attributes {void execute();
}

次要标识接口:颜色

package org.learn.patterns.interfacial.bridge_patterns.hight_level;public interface Color extends Attributes {}

次要具体类:颜色-红色

package org.learn.patterns.interfacial.bridge_patterns.hight_level;public class Red implements Color {@Overridepublic void execute() {System.out.println("涂上红色");}
}

次要标识接口:尺寸

package org.learn.patterns.interfacial.bridge_patterns.hight_level;public interface Size extends Attributes{}

次要具体类:尺寸-L

package org.learn.patterns.interfacial.bridge_patterns.hight_level;public class LargeSize implements Size {@Overridepublic void execute() {System.out.println("尺寸是L");}
}

start

package org.learn.patterns.interfacial.bridge_patterns.hight_level;public class HLMain {public static void main(String[] args) {Toys toy=new Doll(new AttributesFactory(new Red(),new LargeSize()));toy.make();}
}

执行结果

设计模式之接口型设计模式相关推荐

  1. 适配接口 java_【Java 设计模式】接口型模式--Adapter(适配器)模式

    简介:[Java设计模式]接口型模式–Adapter(适配器)模式Adapter模式的宗旨就是:向客户提供接口,并使用现有的类所提供的服务,以满足客户的需求. 或者说,现在有classA的方法满足客户 ...

  2. 设计模式学习1:设计模式简述和设计模式原则

    设计模式简述 什么是设计模式? 软件工程中,设计模式(design pattern)是对软件设计中普遍存在(反复出现)的各种问题,所提出的解决方案. 设计模式的目的: 代码高可用(相同作用的代码能重复 ...

  3. [Head First设计模式]餐馆中的设计模式——命令模式

    系列文章 [Head First设计模式]山西面馆中的设计模式--装饰者模式 [Head First设计模式]山西面馆中的设计模式--观察者模式 [Head First设计模式]山西面馆中的设计模式- ...

  4. java软件设计模式只单例设计模式

    概述 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了可重用代码.让代码更容易被他人理解.保证代码可靠性. 毫无疑问,设计 ...

  5. 精通python设计模式-浅谈Python设计模式 - 原型模式

    声明,本系列文章主要参考<精通Python设计模式>一书,并且参考一些资料,结合自己的一些看法来总结而来. 在<精通Python设计模式>中把设计模式分为三种类型: 创建型模式 ...

  6. 从零开始单排学设计模式「简单工厂设计模式」黑铁 III

    阅读本文大概需要 2 分钟. 本篇是设计模式系列的第二篇,虽然之前也写过相应的文章,但是因为种种原因后来断掉了,而且发现之前写的内容也很渣,不够系统.所以现在打算重写,加上距离现在也有一段时间了,也算 ...

  7. 设计模式示例_状态设计模式示例

    设计模式示例 本文是我们名为" Java设计模式 "的学院课程的一部分. 在本课程中,您将深入研究大量的设计模式,并了解如何在Java中实现和利用它们. 您将了解模式如此重要的原因 ...

  8. 设计模式示例_命令设计模式示例

    设计模式示例 本文是我们名为" Java设计模式 "的学院课程的一部分. 在本课程中,您将深入研究大量的设计模式,并了解如何在Java中实现和利用它们. 您将了解模式如此重要的原因 ...

  9. 设计模式 原型模式_设计模式:原型

    设计模式 原型模式 创新设计模式之一是原型设计模式 . 尽管原型是创造模式,但它在概念上与其他模式有所区别. 我的意思是原型在某种意义上创造了自己. 我将在下面解释. 原型模式的所有魔力都基于Java ...

最新文章

  1. python培训班有用吗-比起自学Python,参加Python培训班有什么优势?
  2. android和ios HybridApp的js交互
  3. ibatis的ibatorForEclipse的安装与配置和ibator的错误日志查看
  4. 190328每日一句 When you forgive, you release.
  5. 吉他扒和弦 扒谱工具Riffstation
  6. 学习笔记12-SG90舵机
  7. android最新固件版本,Android获取系统(ROM)类别及版本号
  8. 小米 Redmi 安装GooglePlay服务
  9. 【边做项目边学Android】手机安全卫士09-手机防盗界面设置向导1
  10. es 集群 number_of_shards、number_of_replicas
  11. 飞机飞行与碰撞问题matlab,建模案例—飞行管理问题.ppt
  12. 2023最新苹果APP上架App Store流程(超详细)
  13. 高性能服务器架构(High-performace Server Architecture)
  14. ASO优化_积分墙优化打量,广告投放策略
  15. redis实战第七篇 使用redis工具(redis-cli)搭建redis cluster
  16. jstat gc命令详解
  17. Java Fx 使用详解
  18. Fly.Box 企业网盘2.2.1 发布
  19. 【Pytorch】torch.Tensor.expand_as()与torch.Tensor.expand()使用与比较
  20. 面试表演了手写HashMap,把面试官给秀到了

热门文章

  1. Redisson--使用/教程/实例
  2. 灵魂有香气的女子李筱懿 :婚姻,是两个人的坚持
  3. Atitit 人的面相 脸型分类 编码与识别 attilax总结
  4. uni-app创建小程序项目并运行到微信开发者工具上@令狐张豪
  5. 西联汇款哪里取钱|怎么取钱
  6. C#开发------对对碰游戏
  7. eureka服务注册与发现机制
  8. SPSS Clementine 数据挖掘入门
  9. Hive面试-情景题总结【包含:建表脚本、数据导入脚本、模拟数据】
  10. 如何调整Outlook 2010日历打印中“每周议程式”的时间范围