博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
设计模式之结构型模式
阅读量:4224 次
发布时间:2019-05-26

本文共 12801 字,大约阅读时间需要 42 分钟。

适配器(Adapter)

Intent

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

Class Diagram

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

JDK

桥接(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(); }}

JDK

  • AWT (It provides an abstraction layer which maps onto the native OS the windowing support.)
  • JDBC

组合(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
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

JDK

  • javax.swing.JComponent#add(Component)
  • java.awt.Container#add(Component)
  • java.util.Map#putAll(Map)
  • java.util.List#addAll(Collection)
  • java.util.Set#addAll(Collection)

装饰者(Decorator)

Intent

为对象动态添加功能,就增加功能而言装饰者比生成子类更加灵活。

Class Diagram

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

Implementation

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

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

设计原则

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

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

JDK

  • java.io.BufferedInputStream(InputStream)
  • java.io.DataInputStream(InputStream)
  • java.io.BufferedOutputStream(OutputStream)
  • java.util.zip.ZipOutputStream(OutputStream)
  • java.util.Collections#checked

外观(Facade)

Intent

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

Class Diagram

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

享元(Flyweight)

Intent

利用共享的方式来支持大量细粒度的对象,这些对象一部分内部状态是相同的。如果一个应用程序使用了大量的对象,可以用较少的共享对象取代很多组对象,可以考虑享元模式。

Class Diagram

  • Flyweight:享元对象
  • IntrinsicState:内部状态,享元对象共享内部状态
  • ExtrinsicState:外部状态,每个享元对象的外部状态不同

Implementation

public interface Flyweight {
void doOperation(String extrinsicState);}
public class ConcreteFlyweight implements Flyweight {
private String intrinsicState; public ConcreteFlyweight(String intrinsicState) {
this.intrinsicState = intrinsicState; } @Override public void doOperation(String extrinsicState) {
System.out.println("Object address: " + System.identityHashCode(this)); System.out.println("IntrinsicState: " + intrinsicState); System.out.println("ExtrinsicState: " + extrinsicState); }}
public class FlyweightFactory {
private HashMap
flyweights = new HashMap<>(); Flyweight getFlyweight(String intrinsicState) {
if (!flyweights.containsKey(intrinsicState)) {
Flyweight flyweight = new ConcreteFlyweight(intrinsicState); flyweights.put(intrinsicState, flyweight); } return flyweights.get(intrinsicState); }}
public class Client {
public static void main(String[] args) {
FlyweightFactory factory = new FlyweightFactory(); Flyweight flyweight1 = factory.getFlyweight("aa"); Flyweight flyweight2 = factory.getFlyweight("aa"); flyweight1.doOperation("x"); flyweight2.doOperation("y"); }}
Object address: 1163157884IntrinsicState: aaExtrinsicState: xObject address: 1163157884IntrinsicState: aaExtrinsicState: y

JDK

Java 利用缓存来加速大量小对象的访问时间。

  • java.lang.Integer#valueOf(int)
  • java.lang.Boolean#valueOf(boolean)
  • java.lang.Byte#valueOf(byte)
  • java.lang.Character#valueOf(char)

代理(Proxy)

Intent

使用代理,控制对其它对象的访问。

Class Diagram

代理有以下四类:

  • 远程代理(Remote Proxy):控制对远程对象(不同地址空间)的访问,它负责将请求及其参数进行编码,并向不同地址空间中的对象发送已经编码的请求。
  • 虚拟代理(Virtual Proxy):根据需要创建开销很大的对象,它可以缓存实体的附加信息,以便延迟对它的访问,例如在网站加载一个很大图片时,不能马上完成,可以用虚拟代理缓存图片的大小信息,然后生成一张临时图片代替原始图片。
  • 保护代理(Protection Proxy):按权限控制对象的访问,它负责检查调用者是否具有实现一个请求所必须的访问权限。
  • 智能代理(Smart Reference):取代了简单的指针,它在访问对象时执行一些附加操作:记录对象的引用次数;当第一次引用一个对象时,将它装入内存;在访问一个实际对象前,检查是否已经锁定了它,以确保其它对象不能改变它。

Implementation

以下是一个虚拟代理的实现,模拟了图片延迟加载的情况下使用与图片大小相等的临时内容去替换原始图片,直到图片加载完成才将图片显示出来。

public interface Image {
void showImage();}
public class HighResolutionImage implements Image {
private URL imageURL; private long startTime; private int height; private int width; public int getHeight() {
return height; } public int getWidth() {
return width; } public HighResolutionImage(URL imageURL) {
this.imageURL = imageURL; this.startTime = System.currentTimeMillis(); this.width = 600; this.height = 600; } public boolean isLoad() {
// 模拟图片加载,延迟 3s 加载完成 long endTime = System.currentTimeMillis(); return endTime - startTime > 3000; } @Override public void showImage() {
System.out.println("Real Image: " + imageURL); }}
public class ImageProxy implements Image {
private HighResolutionImage highResolutionImage; public ImageProxy(HighResolutionImage highResolutionImage) {
this.highResolutionImage = highResolutionImage; } @Override public void showImage() {
while (!highResolutionImage.isLoad()) {
try {
System.out.println("Temp Image: " + highResolutionImage.getWidth() + " " + highResolutionImage.getHeight()); Thread.sleep(100); } catch (InterruptedException e) {
e.printStackTrace(); } } highResolutionImage.showImage(); }}
public class ImageViewer {
public static void main(String[] args) throws Exception {
String image = "http://image.jpg"; URL url = new URL(image); HighResolutionImage highResolutionImage = new HighResolutionImage(url); ImageProxy imageProxy = new ImageProxy(highResolutionImage); imageProxy.showImage(); }}

JDK

  • java.lang.reflect.Proxy
  • RMI

转载地址:http://axgmi.baihongyu.com/

你可能感兴趣的文章
本科大数据专业该怎么上?
查看>>
云创大数据1+X大数据应用部署与调优职业技能等级证书预申报正式开启!
查看>>
人工智能需要一个可被证明的理论作为基础 | 哈佛丘成桐
查看>>
入门 | 一文概览深度学习中的激活函数
查看>>
一分钟整明白Tensorflow Extended
查看>>
人工智能再次参加高考:和作家比写作文,AI能打多少分?
查看>>
云创冬日紫金山踏雪游记
查看>>
西安思源学院电子信息工程学院院长张卫钢一行到访
查看>>
邀请函|欢迎参加2019云创大数据实验平台金融类/电子商务类/数学统计类院校各省总代理招募大会!...
查看>>
云创大数据的2018年!
查看>>
全国高校(高职)大数据师资培训班圆满落幕,200多名老师抢先“尝鲜”!
查看>>
【回顾】云创大数据教育事业部成立
查看>>
云创大数据与江苏城市职业学院共建实习实训就业基地!
查看>>
12月,云创大数据发生了哪些大事?
查看>>
贵州电子商务职业技术学院实验中心主任李崑一行到访
查看>>
善行天下,大爱无疆 ——云创再次获赠爱心锦旗!
查看>>
热烈祝贺刘鹏教授膺选第45届世界技能大赛云计算赛事中国赛区裁判长!
查看>>
图解YU12、I420、YV12、NV12、NV21、YUV420P、YUV420SP、YUV422P、YUV444P的区别
查看>>
QNX简介
查看>>
MQTT协议基本介绍
查看>>