1.代理模式
- 提供对象的替代品或其占位符。 代理控制着对于原对象的访问, 并允许在将请求提交给对象前后进行一些处理
- 结构
- 抽象主题类:通过接口或抽象类声明真实主题和代理对象实现的业务方法
- 真实主题类:实现抽象主题中的具体业务,是代理对象所代理的真实对象,是最终要引用的对象
- 代理类:提供与真实主题相同的接口,其内部含有对真实主题的引用,可以访问、控制或扩展真实主题的功能
2.适配器模式
-
将一个类的接口转换成客户端希望的另外一个接口,使得原本由于接口不兼容而无法工作的类一起工作。适配器分为类适配器模式和对象适配器模式,前者耦合度比后者高。
-
结构
-
目标:当前系统业务所期待的接口,可以是抽象类或接口
-
适配者:它是被访问和适配的现存组件库中的组件接口
-
适配器:转换器,通过继承或引用适配器的对象,把适配者接口转换成目标接口,让客户按目标接口的格式访问适配者
-
-
实现
public interface TfCard { String readTf(); void writeTf(String msg); } public class TfCardImpl implements TfCard{ @Override public String readTf() { return "read TfCard data"; } @Override public void writeTf(String msg) { System.out.println("write TfCard data"+msg); } } public interface SdCard { String readSd(); void writeSd(String msg); } public class SdCardImpl implements SdCard{ @Override public String readSd() { return "read SdCard data"; } @Override public void writeSd(String msg) { System.out.println("write SdCard data"+msg); } } public class Computer { public String readSd(SdCard sdCard) { return sdCard.readSd(); } public void writeTF(SdCard sdCard, String msg) { sdCard.writeSd(msg); } } public class SdAdapterTf implements SdCard{ private TfCard tfCard; public SdAdapterTf(TfCard tfCard) { this.tfCard = tfCard; } @Override public String readSd() { return tfCard.readTf(); } @Override public void writeSd(String msg) { tfCard.writeTf("SdAdapterTf"); } }
-
优缺点
- 优点
- 单一职责可以将接口或数据转换代码从程序主要业务逻辑中分离
- 开闭原则只要客户端代码通过客户端接口与适配器进行交互,就能在不修改客户端代码情况下添加新类型的适配器
- 缺点
- 整体复杂度增加,因为需要新增一系列接口和类,有时直接更改服务器类使其与其它代码兼容会更简单
- 优点
3.装饰者模式
-
不改变现有对象结构的情况下,动态地给该对象增加一些职责
-
结构
-
抽象构件:定义一个抽象接口以规范准备接收附加责任的对象
-
具体构件:实现抽象构件,通过装饰角色为其添加一些职责
-
抽象装饰:继承或实现抽象构件,并包含具体构件的实例,可以通过其子类扩展具体构件的功能
-
具体装饰:实现抽象装饰的相关方法,并给具体构件对象添加附加的责任
-
-
实现
// 抽象构件角色 @Data public abstract class FastFood { private float price; private String desc; public FastFood(float price, String desc) { this.price = price; this.desc = desc; } public abstract float cost(); } // 具体构件角色 public class FriedRice extends FastFood{ public FriedRice() { super(10,"炒饭"); } @Override public float cost() { return getPrice(); } } // 抽象装饰 public abstract class Garnish extends FastFood { private FastFood fastFood; public FastFood getFastFood() { return fastFood; } public void setFastFood(FastFood fastFood) { this.fastFood = fastFood; } public Garnish(float price, String desc, FastFood fastFood) { super(price, desc); this.fastFood = fastFood; } } // 具体装饰 public class Egg extends Garnish { public Egg(FastFood fastFood) { super(1, "鸡蛋", fastFood); } @Override public float cost() { return getPrice() + getFastFood().cost(); } @Override public String getDesc() { return super.getDesc() + getFastFood().getDesc(); } }
-
优点与缺点
- 优点
- 无需创建新子类即可扩展对象的行为
- 以在运行时添加或删除对象的功能
- 用多个装饰封装对象来组合几种行为
- 单一职责原则, 你可以将实现了许多不同行为的一个大类拆分为多个较小的类
- 缺点
- 在封装器栈中删除特定封装器比较困难
- 实现行为不受装饰栈顺序影响的装饰比较困难
- 各层的初始化配置代码看上去可能会很糟糕
- 优点
4.桥接模式
-
抽象与实现分离,使它们可以独立变化,用组合关系替代继承方式来实现,降低抽象和实现这两个可变维度的耦合度
-
结构
-
抽象化:定义抽象类,包含一个对实例化对象的引用
-
扩展抽象化:抽象化角色的子类,实现父类中的业务方法,通过组合关系调用实现化角色中的业务方法
-
实现化:定义实现化角色的接口,供扩展抽象化角色调用
-
具体实现化:实现化角色接口的具体实现
-
-
实现
// 实现化角色 public interface VideoFile { void decode(String fileName); } // 具体实现化角色 public class RmVbFile implements VideoFile { @Override public void decode(String fileName) { System.out.println("RmVbFile:" + fileName); } } // 抽象化角色 public abstract class OperatingSystem { protected VideoFile videoFile; public OperatingSystem(VideoFile videoFile) { this.videoFile = videoFile; } public abstract void playString(String fileName); } // 扩展抽象化 public class Mac extends OperatingSystem{ @Override public void playString(String fileName) { videoFile.decode("mac:"+fileName); } public Mac(VideoFile videoFile) { super(videoFile); } }
优点与缺点
- 优点
- 可以创建与平台无关的类和程序
- 客户端代码仅与高层抽象部分进行互动, 不会接触到平台的详细信息
- 开闭原则。 你可以新增抽象部分和实现部分, 且它们之间不会相互影响
- 单一职责原则。 抽象部分专注于处理高层逻辑, 实现部分处理平台细节
- 缺点
- 对高内聚的类使用该模式可能会让代码更加复杂。
5.外观模式
-
别名门面模式,通过多个复杂子系统提供一个一致的接口,而使这些子系统更加容易被访问的模式。该模式对外有一个统一接口,外部应用程序不用关心内部子系统的具体细节,大大降低应用程序的复杂性,提供程序的可维护性
-
结构
-
外观:多个子系统对外提供一个共同的接口
-
子系统:实现系统的部分功能,客户可以通过外观角色访问它
-
-
实现
// 外观 public class SmartApplicationFacade { private Light light; private Tv tv; public SmartApplicationFacade() { this.light = new Light(); this.tv = new Tv(); } public void say(String msg) { if (msg.contains("开启")) { on(); } else if (msg.contains("关闭")) { off(); } else { System.out.println("听不懂"); } } private void on(){ light.on(); tv.on(); } private void off(){ light.off(); tv.off(); } } // 子系统 public class Light { public void on(){ System.out.println("开灯"); } public void off(){ System.out.println("关灯"); } } public class Tv { public void on(){ System.out.println("开电视"); } public void off(){ System.out.println("关电视"); } }
-
优缺点
- 优点
- 代码独立于复杂子系统
- 缺点
- 外观可能成为与程序中所有类都耦合的对象
- 优点
6.组合模式
-
又名整体模式,用于把一组相似对象当作一个单一的对象。组合模式依据树形结构来组合对象,用来表示部分以及整体层次,这种类型的设计模式属于结构型模式,它创建了对象组的树形结构
-
结构
-
抽象根节点:定义系统各层次对象的共有方法和属性,预先定义一些默认行为和属性
-
树枝节点:定义树枝节点的行为,存储子节点,组合树枝节点和叶子节点形成一个树形结构
-
叶子结点:叶子节点对象,其下再无分枝,是系统层次遍历的最小单位
-
-
实现
// 抽象根节点 public abstract class MenuComponent { protected String name ; protected int level; public void add(MenuComponent menuComponent){ throw new UnsupportedOperationException(); } public void remove(MenuComponent menuComponent){ throw new UnsupportedOperationException(); } public MenuComponent getChild(int index){ throw new UnsupportedOperationException(); } public String getName(){ return name; } public abstract void print(); } // 树枝节点 public class Menu extends MenuComponent { List<MenuComponent> menuComponentList = new ArrayList<>(); public Menu(String name, int level) { super.name = name; super.level = level; } @Override public void add(MenuComponent menuComponent) { menuComponentList.add(menuComponent); } @Override public void remove(MenuComponent menuComponent) { menuComponentList.remove(menuComponent); } @Override public MenuComponent getChild(int index) { return menuComponentList.get(index); } @Override public void print() { for (int i = 0; i < level; i++) { System.out.print("-"); } System.out.println(name); for (MenuComponent menuComponent : menuComponentList) { menuComponent.print(); } } } // 叶子结点 public class MenuItem extends MenuComponent { public MenuItem(String name, int level) { super.name = name; super.level = level; } @Override public void print() { for (int i = 0; i < level; i++) { System.out.print("-"); } System.out.println(name); } }
-
优缺点
- 优点
- 利用多态和递归机制更方便地使用复杂树结构
- 开闭原则 无需更改现有代码, 你就可以在应用中添加新元素, 使其成为对象树的一部分
- 缺点
- 对于功能差异较大的类,提供公共接口或许会有困难,在特定情况下,你需要过度一般化组件接口,使其变得令人难以理解。
- 优点
7.享元模式
-
运用共享技术来有效地支持大量细粒度对象的复用,通过共享已经存在的对象来大幅度减少需要创建的对象数量、避免大量相似对象的开销,从而提高系统资源的利用率
-
结构
-
享元模式中存在两种状态:
- 内部状态:不会随着环境的改变而改变的可共享部分
- 外部状态:随环境改变而改变的不可以共享的部分,享元模式的实现要领就是区分应用中的这两种状态,并将外部状态外部化
-
抽象享元角色:通常是一个接口或抽象类,在抽象享元类中声明了具体享元类公共的方法,这些方法可以向外界提供享元对象的内部数据,同时也可以通过这些方法来设置外部数据
-
具体享元:实现抽象享元类,称为享元对象,在具体享元类中为内部状态提供了存储空间,通常我们可以结合单例模式来设计具体享元类,为每一个具体享元类提供唯一的享元对象
-
非享元:并不是所有的抽象享元类的子类都需要被共享,不能被共享的子类可设计为非共享具体享元类,当需要一个非共享具体享元类的对象时可以直接通过实例化创建
-
享元工厂:负责创建和管理享元角色,当客户对请求一个享元对象时,享元工厂检查系统中是否存在符合要求的享元对象,如果存在则提供给角色,如果不存在则创建一个新的享元对象
-
优缺点
- 优点
- 程序中有很多相似对象, 那么你将可以节省大量内存
- 缺点
- 需要牺牲执行速度来换取内存, 因为他人每次调用享元方法时都需要重新计算部分情景数据