关于java:23种设计模式Java版第四篇

38次阅读

共计 5424 个字符,预计需要花费 14 分钟才能阅读完成。

ps:本文系转载文章,浏览原文可获取源码,文章开端有原文链接

ps:这一篇是写桥接模式、组合模式和享元模式

1、桥接模式

形象局部与它的实现局部进行独立,让他们进行独立变动;将继承关系转变成组合关系,使得形象和实现这两个的耦合度升高了,缩小了代码量。

桥接模式有以下几个角色:

(1)抽象化角色:定义一个抽象类或者一般类,它的一个属性持有一个对实现化对象。

(2)扩大抽象化角色:抽象化角色的子类,实现父类中的形象办法或者重写父类办法,在构造方法调用父类结构传递实现化角色,使得调用实现化角色中的业务办法是采纳组合关系来实现。

(3)实现化角色:定义实现化角色的接口,给抽象化角色所调用。

(4)具体实现化角色:实现实现化角色的接口。

上面用桥接模式通过代码来举例一下:

(1)实现化角色,写一个 Brand 接口:

public interface Brand {

public void sale();

}

(2)具体实现化角色,写一个 Lenovo 类并实现 Brand 接口:

class Lenovo implements Brand {

@Override
public void sale() {

System.out.print("联想");

}

}

(3)具体实现化角色,写一个 Shenzhou 类并实现 Brand 接口:

class Shenzhou implements Brand {

@Override
public void sale() {

System.out.print("神舟");

}

}

(4)抽象化角色,写一个 Computer 类:

public class Computer {

public Brand brand;
public Computer(Brand brand) {this.brand = brand;}
public void sale() {brand.sale();
}

}

(5)扩大抽象化角色,写一个 Desktop 类并继承 Computer 类:

class Desktop extends Computer {

public Desktop(Brand brand) {

super(brand);

}
@Override
public void sale() {

super.sale();
System.out.println("台式机");

}
}

(6)扩大抽象化角色,写一个 Laptop 类并继承 Computer 类:

class Laptop extends Computer {

public Laptop(Brand brand) {

super(brand);

}
@Override
public void sale() {

super.sale();
System.out.println("笔记本");

}
}

(7)客户端进行测试调用:

    Computer computer = new Desktop(new Shenzhou());
    computer.sale();
    Computer computer2 = new Desktop(new Lenovo());
    computer2.sale();

日志打印如下所示:

形象局部与它的实现局部进行独立就好比例子中的 Desktop 和 Shenzhou 独立开来;将继承关系转变成组合关系就好比 Computer 的子类和 Brand 子类进行组合。

桥接模式的实现细节既能够客户通明也能够对用户暗藏,设计出了比继承更好的思维,可能做到拆散形象和实现;因为聚合关联关系建设在形象层,所以给开发者了解起来没那么容易以及减少肯定的设计难度;两个维度独立的变动,所以应用范畴内具备肯定的局限性。

2、组合模式

一种将对象组合成树状的层次结构的模式,形容整体与局部的关系,使得用户对单个对象和组合对象的应用具备一致性;它是把对象组合到树形构造中,顶层的节点被称为根节点,根节点上面又蕴含树枝节点和叶子节点,树枝节点上面又能够呈现树枝节点和叶子节点;就好比文件夹,根文件夹上面还有子文件夹和文件,子文件夹上面还有文件夹和文件。

组合模式具备以下几个角色:

(1)形象构件角色:为树叶构件和树枝构件申明一个公同的接口,给它们的默认行为进行实现。

(2)树叶构件角色:叶子节点对象,它没有子节点,形象构件角色的子类,就好比电脑中的文件。

(3)树枝构件角色:分支节点对象,它有子节点,形象构件角色的子类,就好比电脑中的文件夹存储和治理子文件夹和子文件。

上面用代码来进行举例并演示:

(1)形象构件角色,写一个 AbstractFile 接口:

public interface AbstractFile {
public void killVirus();
}

(2)树叶构件角色,写一个 ImageFile 类并实现 AbstractFile 接口:

class ImageFile implements AbstractFile {

private String name;

public ImageFile(String name) {

    this.name = name;

}

@Override
public void killVirus() {

System.out.println("图片文件" + name + "查杀");

}

}

(3)树叶构件角色,写一个 TextFile 类并实现 AbstractFile 接口:

class TextFile implements AbstractFile {

private String name;

public TextFile(String name) {

    this.name = name;

}

@Override
public void killVirus() {

System.out.println("文本文件" + name + "查杀");

}

}

(4)树叶构件角色,写一个 VideoFile 类并实现 AbstractFile 接口:

class VideoFile implements AbstractFile {

private String name;

public VideoFile(String name) {

    this.name = name;

}

@Override
public void killVirus() {

System.out.println("视频文件" + name + "查杀");

}

}

(5)树枝构件角色,写一个 Folder 类并实现 AbstractFile 接口:

class Folder implements AbstractFile {

private String name;
private List<AbstractFile> list = new ArrayList<AbstractFile>();
public Folder(String name) {

 this.name = name;

}
public void add(AbstractFile file) {

  list.add(file);

}
public void remove(AbstractFile file) {

  list.remove(file);

}
public AbstractFile get(int index) {

  return list.get(index);

}
@Override
public void killVirus() {

System.out.println("文件夹" + name + "查杀");
for (AbstractFile file: list) {file.killVirus();
}

}

}

客户端进行调用测试:

   AbstractFile f2,f3,f4,f5;
   Folder f1 = new Folder("我的文件夹");
   f2 = new ImageFile("我的图片");
   f3 = new TextFile("我的文本文件");
   f1.add(f2);
   f1.add(f3);
   
   Folder f11 = new Folder("我的电影");
   f4 = new VideoFile("神雕侠侣");
   f5 = new VideoFile("笑傲江湖");
   f11.add(f4);
   f11.add(f5);
   f1.add(f11);
   f1.killVirus();

日志打印如下所示:

这里是模拟电脑查杀文件的过程,从这里看出,f1 相当于根目录,f2 和 f3 是 f1 目录下的文件,f11 是 f1 目录下的文件夹,而 f11 又蕴含了 f4 和 f5 这 2 个文件。

客户端代码能够全副解决单个对象和组合对象,毋庸关怀组合对象与单个对象的不同,而可能对立地应用组合构造中的所有对象;在组合体内退出新的对象,客户端中不会更改原有的代码;然而客户端须要花工夫分清类之间的档次关系,限度容器中的构件也有肯定的难度。

3、享元模式

通过共享的技术让多个雷同的对象不用每个都去实例化一个对象,只须要共享一份就能够了,这样防止大量类似类的开销,从而进步系统资源的利用率。

享元模式具备以下几种角色:

(1)形象享元角色:具体享元角色的父类,给子类提供标准须要实现的接口。

(2)具体享元角色:形象享元角色的子类,实现形象享元角色中标准的接口。

(3)非享元角色:内部不可共享的状态,它作为享元角色办法中的参数。

(4)享元工厂角色:创立和存储享元角色,当客户端申请创立一个享元对象时,它就会查看是否有符合要求的享元对象,如果有就从存储中拿进去;如果没有就创立一个新的享元对象并存储起来。

咱们以五子棋为例子,五子棋中的黑白棋子,它们尽管坐标点不同,然而色彩就只分为 2 种,雷同色彩的棋子共用一种色彩,不用再创立一个同种色彩的对象;上面用代码进行演示一下:

(1)形象享元角色,写一个 ChessFlyWeight 接口:

public interface ChessFlyWeight {

public void setColor(String c);
public String getColor();
public void display(Coordinate c);

}

(2)具体享元角色,写一个 ConcreteChess 类并实现 ChessFlyWeight 接口:

class ConcreteChess implements ChessFlyWeight {
private String color;

public ConcreteChess(String color) {

super();
this.color = color;

}

@Override
public void setColor(String c) {

this.color = c;

}

@Override
public String getColor() {

return color;

}

@Override
public void display(Coordinate c) {

System.out.println("棋子色彩" + color);
System.out.println("棋子地位" + c.getX() + ":" + c.getY());

}

}

(3)非享元角色,写一个 Coordinate 类:

public class Coordinate {
private int x,y;

public Coordinate(int x, int y) {

super();
this.x = x;
this.y = y;

}

public int getX() {

return x;

}

public void setX(int x) {

this.x = x;

}

public int getY() {

return y;

}

public void setY(int y) {

this.y = y;

}

}

(4)享元工厂角色,写一个 ChessFlyWeightFactotry 类:

public class ChessFlyWeightFactotry {

private static Map<String, ChessFlyWeight> map = new HashMap<String,ChessFlyWeight>();
public static ChessFlyWeight getChess(String color){if (map.get(color) != null) {return map.get(color);
  } else {ChessFlyWeight chessFlyWeight = new ConcreteChess(color);
    map.put(color, chessFlyWeight);
    return chessFlyWeight;
  }
}

}

客户端进行测试:

     ChessFlyWeight c1 = ChessFlyWeightFactotry.getChess("彩色");
     ChessFlyWeight c2 = ChessFlyWeightFactotry.getChess("彩色");
     System.out.println(c1);
     System.out.println(c2);
     System.out.println("减少内部解决 -------------------");
     c1.display(new Coordinate(10, 10));
     c2.display(new Coordinate(20, 20));

日志打印如下所示:

从这里咱们能够看到,当咱们要两次拿彩色棋子的时候 ChessFlyWeightFactotry 会查看是否有彩色棋子的对象,第一次拿彩色棋子的时候,显著没有彩色棋子就创立一个 ConcreteChess 类对象;当第二次拿的时候,查看到存在彩色的棋子,即 ConcreteChess 类对象,便把 ConcreteChess 类对象拿进去应用,所以 c1 和 c2 是同一个对象,这个有点相似单例模式。

享元模式中领有同一种个性的具体享元对象只存在一个,这大大减少了零碎中对象的数量,缩小了零碎性能的开销;然而不可避免的应用内部不可共享的状态,这给程序设计带来肯定的复杂性。

正文完
 0