软件设计师——设计模式笔记中(结构型7种)
6、适配器模式(对象模式)
意图
将一个类的接口转换成客户希望的另外一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。(转换,兼容接口)
适用性
- 想使用一个已经存在的类,而它的接口不符合要求。
- 想创建一个可以服用的类,该类可以与其他不相关的类或不可预见的类(即那些接口可能不一定兼容的类)协同工作。
- (仅适用于对象Adapter)想使用一个已经存在的子类,但是不可能对每一个都进行子类化以匹配它们的接口。对象适配器可以适配它的父类接口。
代码实现
//6 适配器模式
public class AdapterPattern {
public static void main(String[] args) {
//给usb接口插上type-c适配器
USB usb = new Adapter();
usb.Request();
}
}
class USB {
public void Request() {
System.out.println("USB数据线");
}
}
class TypeC {
public void SpecificRequest() {
System.out.println("Type-C数据线");
}
}
//适配器:将USB适配成type-c
class Adapter extends USB {
private TypeC typeC = new TypeC();
@Override
public void Request() {
typeC.SpecificRequest();
}
}
运行结果
TypeC数据线
7、桥接模式(对象模式)
意图
将抽象部分与实现部分分离,使它们都可以独立的变化。(抽象和实现分离)
适用性
- 不希望在抽象和它的实现部分之间有一个固定的绑定关系。例如,这种情况可能是因为,在程序运行时刻实现部分应可以被选择或者切换。
- 类的抽象以及它的实现都应该可以通过生成子类的方法加以扩充。这是Bridge模式使得开发者可以对不同的抽象接口和实现部分进行组合,并分别对它们进行扩充。
- 对一个抽象的实现部分的修改应对客户不产生影响,即客户代码不必重新编译。 (C++)想对客户完全隐藏抽象的实现部分。
- 有许多类要生成的类层次结构。
- 想在多个对象间共享实现(可能使用引用计数),但同时要求客户并不知道这一点。
代码实现
//7 桥接模式
public class BridgePattern {
public static void main(String[] args) {
Product product1 = new ProductX();
Product product2 = new ProductX();
//设置产品名字
product1.setName("旺仔");
//设置产品颜色
product1.setColor(new Red());
product1.Operation();
product2.setName("脉动");
product2.setColor(new Blue());
product2.Operation();
}
}
//产品类
abstract class Product {
private String name;
protected Color color;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setColor(Color color) {
this.color = color;
}
public abstract void Operation();
}
//还可以创建例如ProductY的产品类,让产品多样化
class ProductX extends Product {
@Override
public void Operation() {
color.OperationImp(this.getName());
}
}
//颜色接口
interface Color {
public void OperationImp(String name);
}
//红色
class Red implements Color {
@Override
public void OperationImp(String name) {
System.out.println(name + ":红色");
}
}
//蓝色
class Blue implements Color {
@Override
public void OperationImp(String name) {
System.out.println(name + ":蓝色");
}
}
运行结果
旺仔:红色
脉动:蓝色
8、组合模式(对象模式)
意图
将对象组合成树形结构以表示"部分-整体"的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。(整体-部分,树形结构)
适用性
- 想表示对象的部分整体层次结构。
- 希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。
代码实现
import java.util.*;
public class CompositePattern {
public static void main(String[] args) {
// 父类名 对象名 = new 子类名();
AbstractFile root = new Folder("root");
AbstractFile folderA = new Folder("folderA");
AbstractFile folderB = new Folder("folderB");
AbstractFile fileC = new File("fileC");
AbstractFile fileD = new File("fileD");
AbstractFile fileE = new File("fileE");
root.Add(folderA); //将文件夹A添加到根文件夹下
root.Add(folderB); //将文件B添加到根文件夹下
root.Add(fileC); //将文件C添加到根文件夹下
folderA.Add(fileD); //将文件夹D添加到文件夹A下
folderA.Add(fileE); //将文件E添加到文件夹A下
paint(root);
System.out.print("\n");
root.Remove(fileC); //删除文件C
paint(root);
}
static void print(AbstractFile file) {
file.printName();
List<AbstractFile> childrenList = file.getChildren();
if (childrenList == null) return;
// for (对象类型 对象名 : 遍历对象)
for (AbstractFile children : childrenList) {
// children.printName();
print(children);
}
}
}
abstract class AbstractFile {
protected String name;
public void printName() {
System.out.println(name);
}
public abstract boolean Add(AbstractFile file);
public abstract boolean Remove(AbstractFile file);
public abstract List<AbstractFile> getChildren();
}
class Folder extends AbstractFile {
private List<AbstractFile> childrenList = new ArrayList<AbstractFile>();
public Folder(String name) {
this.name = name;
}
@Override
public boolean Add(AbstractFile file) {
return childrenList.add(file);
}
@Override
public boolean Remove(AbstractFile file) {
return childrenList.remove(file);
}
@Override
public List<AbstractFile> getChildren() {
return childrenList;
}
}
class File extends AbstractFile {
public File(String name) {
this.name = name;
}
//文件下面不能添加文件及文件夹
@Override
public boolean Add(AbstractFile file) {
return false;
}
//文件下面不能移除文件及文件夹
@Override
public boolean Remove(AbstractFile file) {
return false;
}
//文件没有文件及文件夹
@Override
public List<AbstractFile> getChildren() {
return null;
}
}
运行结果
root
folderA
folderB
fileC
fileD
fileE
root
folderA
folderB
fileD
fileE
9、装饰器模式(对象模式)
意图
动态地给一个对象添加一些额外的职责。就增加功能来说,装饰器模式相比生成子类更为灵活。(附加职责)
适用性
- 在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。
- 处理那些可以撤销的职责。
- 当不能采用生成子类的方式进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是, 由于类定义被隐藏,或类定义不能用于生成子类。
代码实现
public class DecoratorPattern {
public static void main(String[] args) {
Person zhangsan = new Student("张三");
zhangsan = new DecoratorA(zhangsan);
zhangsan.Operation();
System.out.println("\n===================");
zhangsan = new DecoratorB(zhangsan);
zhangsan.Operation();
System.out.println("\n===================");
// 对象链
Person list = new DecoratorB(new DecoratorA(new Student("李四")));
list.Operation();
}
}
abstract class Person {
protected String name;
public abstract void Operation();
}
class Student extends Person {
public Student(String name) {
this.name = name;
}
@Override
public void Operation() {
System.out.print(name + "的职责:学习 "); //基础职责
}
}
abstract class Decorator extends Person {
protected Person person;
}
//第一个装饰器
class DecoratorA extends Decorator {
public DecoratorA(Person person) {
this.person = person;
}
@Override
public void Operation() {
person.Operation(); // 基础职责
System.out.print("写作业 "); //在基础职责后添加的职责
}
}
//第二个装饰器
class DecoratorB extends Decorator {
public DecoratorB(Person person) {
this.person = person;
}
@Override
public void Operation() {
person.Operation(); // 基础职责
System.out.print("考试 "); //在基础职责后添加的职责
}
}
运行结果
张三的职责:学习 写作业
===================
张三的职责:学习 写作业 考试
===================
李四的职责:学习 写作业 考试
10、外观模式(对象模式)
意图
定义了一个高层接口,为子系统中的一组接口提供一个一致的界面,使得这一子系统更加容易使用。(对外统一接口)
适用性
- 要为一个复杂子系统提供一个简单接口时,子系统往往因为不断演化而变得越来越复杂。大多数模式使用时都会产生更多更小的类,这使得子系统更具有可重用性,也更容易对子系统进行定制,但也给那些不需要定制子系统的用户带来一些使用上的困难。Facade可以提供一个简单的默认视图,这一视图对大多数用户来说已经足够,而那些需要更多的可定制性的用户可以越过Facade层。
- 客户程序与抽象类的实现部分之间存在着很大的依赖性。引入Facade将这个子系统与客户以及其他的子系统分离,可以提高子系统的独立性和可移植性。
- 当需要构建一个层次结构的子系统时,使用Facade模式定义子系统中每层的入口点。如果子系统之间是相互依赖的,则可以让它们仅通过Facade进行通信,从而简化了它们之间的依赖关系。
代码实现
public class FacadePattern {
public static void main(String[] args) {
Facade facade = new Facade();
facade.methodA();
facade.methodB();
facade.methodC();
}
}
class Facade{
SubSystemA subSystemA;
SubSystemB subSystemB;
SubSystemC subSystemC;
public Facade(){
subSystemA = new SubSystemA();
subSystemB = new SubSystemB();
subSystemC = new SubSystemC();
}
public void methodA(){
subSystemA.method1();
}
public void methodB(){
subSystemB.method2();
}
public void methodC(){
subSystemC.method3();
}
}
class SubSystemA{
public void method1(){
System.out.println("执行子系统一的功能");
}
}
class SubSystemB{
public void method2(){
System.out.println("执行子系统二的功能");
}
}
class SubSystemC{
public void method3(){
System.out.println("执行子系统三的功能");
}
}
运行结果
执行子系统一的功能
执行子系统二的功能
执行子系统三的功能
11、享元模式(对象模式)
意图
提供支持大量细粒度对象共享的有效方法。(细粒度,共享)
适用性
- 一个应用程序使用了大量的对象。
- 完全由于使用大量的对象,造成很大的存储开销。
- 对象的大多数状态都可变为外部状态。
- 如果删除对象的外部状态,那么可以用相对较少的共享对象取代很多组对象。
- 应用程序不依赖于对象标识。由于Flyweight 对象可以被共享,所以对于概念上明显有别的对象,标识测试将返回真值。
代码实现
public class FlyWeightPattern {
public static void main(String[] args) {
PieceFactory pieceFactory = new PieceFactory();
Piece whitePiece1 = pieceFactory.getPiece(0);
System.out.println(whitePiece1);
whitePiece1.draw(2022,528);
Piece whitePiece2 = pieceFactory.getPiece(0); //共享pieceFactory.getPiece(0);
System.out.println(whitePiece2);
whitePiece2.draw(2023,529); //两个白色棋子坐标不同,但地址相同,都是@1b6d3586
System.out.println("============================================");
Piece blackPiece1 = pieceFactory.getPiece(1);
System.out.println(blackPiece1);
blackPiece1.draw(2024,610);
Piece blackPiece2 = pieceFactory.getPiece(1); //共享pieceFactory.getPiece(1);
System.out.println(blackPiece2);
blackPiece2.draw(2001,121); //两个黑色棋子坐标不同,但地址相同,都是@4554617c
}
}
class PieceFactory{
private Piece[] pieces= {new WhitePiece(),new BlackPiece()};
public Piece getPiece(int key){
if (key == 0){
return pieces[0];
}
else {
return pieces[1];
}
}
}
abstract class Piece{
protected String color;
public abstract void draw(int x,int y);
}
class WhitePiece extends Piece{
public WhitePiece(){
this.color = "white";
}
@Override
public void draw(int x, int y) {
System.out.println("draw a color:" + color + "piece x:" + x + " y:" + y + "\n");
}
}
class BlackPiece extends Piece{
public BlackPiece(){
this.color = "black";
}
@Override
public void draw(int x, int y) {
System.out.println("draw a color:" + color + "piece x:" + x + " y:" + y + "\n");
}
}
运行结果
Shejims.FlyWeightPattern.WhitePiece@1b6d3586
draw a color:whitepiece x:2022 y:528
Shejims.FlyWeightPattern.WhitePiece@1b6d3586
draw a color:whitepiece x:2023 y:529
============================================
Shejims.FlyWeightPattern.BlackPiece@4554617c
draw a color:blackpiece x:2024 y:610
Shejims.FlyWeightPattern.BlackPiece@4554617c
draw a color:blackpiece x:2001 y:121
12、代理模式(对象模式)
意图
为其他对象提供一种代理以控制对这个对象的访问。(代理控制)
适用性
- 远程代理(Remote Proxy)为一个对象在不同地址空间提供局部代表。
- 虚代理(Virtual Proxy)根据需要创建开销很大的对象。
- 保护代理(Protection Proxy)控制对原始对象的访问,用于对象应该有不同的访问权限的时候。
- 智能引用( Smart Reference)取代了简单的指针,它在访问对象时执行一些附加操作。典型用途包括:对指向实际对象的引用计数,这样当该对象没有引用时,可以被自动释放;当第一次引用一个持久对象时,将它装入内存;在访问一个实际对象前,检查是否已经锁定了它,以确保其他对象不能改变它。
代码实现
public class ProxyPattern {
public static void main(String[] args) {
RealSubject realSubject = new RealSubject();
Proxy proxy = new Proxy(realSubject);
proxy.buy();
}
}
interface Subject {
public void buy();
}
//代理负责代理工作
class Proxy implements Subject {
protected RealSubject realSubject;
public Proxy(RealSubject realSubject) {
this.realSubject = realSubject;
}
@Override
public void buy() {
System.out.println("办理购买前的手续");
realSubject.buy(); //应真正的主题的要求付钱
System.out.println("办理购买后的手续");
}
}
//真正的主题只顾付钱,不需要知道过程,只需要结果,过程由代理完成
class RealSubject implements Subject {
@Override
public void buy() {
System.out.println("付钱");
}
}
运行结果
办理购买前的手续
付钱
办理购买后的手续