0%

Java设计模式-结构型模式

一、适配器模式

适配器模式(Adapter Pattern):结构型模式之一,将一个类的接口转换成客户希望的另一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的哪些类可以一起工作

适配器模式结构

  • 目标抽象类:该角色把其他类转换为我们期望的接口,可以是一个抽象类或接口,也可以是具体类。
  • 被适配者:原有的接口,也是希望被适配的接口。
  • 适配者:将被适配者和目标抽象类组合到一起的类。

适配器的实现又分为:类适配器、对象适配器、接口适配器

1.1 实现

1.1.1 类适配器

通过类来实现适配器,以类来继承和实现接口的方式,来获取被适配类的信息并转换输出重写到适配接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// 被适配者
public class Adaptee {
public void adapterRequest(){
System.out.println("被适配者的方法");
}
}

// 目标接口
public interface Target {
void request();
}

// 适配器
public class Adapter extends Adaptee implements Target {
@Override
public void request() {
super.adapterRequest();
}
}

// 测试类
public class Test {
public static void main(String[] args) {
Target adapterTarget = new Adapter();
adapterTarget.request();
}
}

1.1.2 对象适配器

调整适配器的实现方式,不再以继承的方式调用被适配者的信息,而是通过对象的方式获取信息

1
2
3
4
5
6
7
8
public class Adapter implements Target {
// 获取被适配者对象
private Adaptee adaptee = new Adaptee();

public void request() {
adaptee.adapterRequest();
}
}

1.1.3 接口适配器

因为类继承接口需要实现全部接口中的方法,有时我们只需要实现部分的接口方法,所以这里就需要使用抽象类来继承接口并实现接口全部方法,生成对象时,需要用到哪个方法就重写哪个方法即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// 目标接口
public interface Target {
void request();
void getTypeA();
void getTypeB();
}

// 适配器类
public abstract class Adapter extends Adaptee implements Target {
public void request() {
return null;
}

public void getTypeA(){
return null;
}
public void getTypeB(){
return null;
}
}

// 测试类
public class AdapterTest {
public static void main(String[] args) {
Target adapterTarget= new Adapter() {
@Override
public void request() {
return super.adapterRequest();
}
};

adapterTarget.request();
}
}

二、代理模式

代理模式的角色:

  • 抽象主题(Subject)类:通过接口或抽象类声明真实主题和代理对象实现的业务方法

  • 真实主题(Real Subject)类:实现了抽象主题中的具体业务,是代理对象所代表的真实对象,是最终要引用的对象。

  • 代理(Proxy)类:提供了与真实主题相同的接口,其内部含有对真实主题的引用,它可以访问、控制或扩展真实主题的功能。

代理一般理解为代码增强,即在不修改源代码的逻辑上增加一些逻辑代码

代理模式分为静态代理和动态代理:

  • 静态:由程序员创建代理类或特定工具自动生成源代码再对其编译,在程序运行前代理类的 .class 文件就已经存在了。
  • 动态:在程序运行时,运用反射机制动态创建而成

2.1 实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
package proxy;

// 测试类
public class ProxyTest {
public static void main(String[] args) {
Proxy proxy = new Proxy();
proxy.Request();
}
}

//抽象主题
interface Subject {
void Request();
}

//真实主题
class RealSubject implements Subject {
public void Request() {
System.out.println("访问真实主题方法...");
}
}

//代理类
class Proxy implements Subject {
private RealSubject realSubject;

public void Request() {
if (realSubject == null) {
realSubject = new RealSubject();
}
preRequest();
realSubject.Request();
postRequest();
}

public void preRequest() {
System.out.println("访问真实主题之前的预处理。");
}

public void postRequest() {
System.out.println("访问真实主题之后的后续处理。");
}
}

2.2 应用

  • Spring框架的的AOP(面向切面编程)概念

三、桥接模式

桥接模式的角色:

  • 抽象化角色Abstraction:定义抽象类,并包含一个对实现化对象的引用
  • 扩展抽象化角色Refined Abstraction:抽象化角色的子类,实现父类中的业务方法
  • 实现化角色Implementor:实现化角色的接口,供扩展抽象化角色调用
  • 具体实现化角色Concrete Implementor:给出实现化角色接口的具体实现

简单来说就是通过抽象化角色完成对实现化角色方法的调用

桥接模式是将抽象与实现分离,这里的抽象是抽象化角色,实现是实现化角色,两者以组合关系完成抽象化角色实现化角色方法的调用

3.1 实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package bridge;
public class BridgeTest {
public static void main(String[] args) {
Implementor imple = new ConcreteImplementorA();
Abstraction abs = new RefinedAbstraction(imple);
abs.Operation();
}
}
//实现化角色
interface Implementor {
public void OperationImpl();
}
//具体实现化角色
class ConcreteImplementorA implements Implementor {
public void OperationImpl() {
System.out.println("具体实现化(Concrete Implementor)角色被访问");
}
}
//抽象化角色
abstract class Abstraction {
protected Implementor imple;
protected Abstraction(Implementor imple) {
this.imple = imple;
}
public abstract void Operation();
}
//扩展抽象化角色
class RefinedAbstraction extends Abstraction {
protected RefinedAbstraction(Implementor imple) {
super(imple);
}
public void Operation() {
System.out.println("扩展抽象化(Refined Abstraction)角色被访问");
imple.OperationImpl();
}
}

3.2 应用

四、装饰模式

装饰模式角色:

  • Component(抽象构件类):是具体构件以及抽象装饰类的父类,声明了在具体构件中实现的业务方法,它的引入可以使客户端以一致的方式处理未被装饰之后的对象,以实现客户端的透明操作
  • ConcreteComponent(具体构件类):是抽象构件类的子类,用于定义具体的构件对象,实现了在抽象构件中声明的方法,装饰器可以给它增加额外的职责
  • Decorator(抽象装饰类)用于给具体构件类增加职责,但是具体职责在子类实现。抽象装饰类维护一个指向抽象构件的引用,通过该引用可以调用装饰之前构件对象的方法,并通过子类扩展该方法以达到装饰的目的
  • ConcreteDecorator(具体装饰类)负责向构件中添加新的职责,每一个具体装饰类都定义了一些新的行为,可以调用抽象装饰类中定义的方法,并可以增加新的职责用以扩充对象的行为

4.1 实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
// 抽象构建类
abstract class Component
{
abstract void operation();
}

// 具体构建类
class ConcreteComponent extends Component
{
public void operation()
{
System.out.println("具体构件方法");
}
}

// 抽象构建类
class Decorator extends Component
{
private Component component;

public Decorator(Component component)
{
this.component = component;
}

public void operation()
{
component.operation();
}
}

// 具体装饰类
class ConcreteDecorator extends Decorator
{
public ConcreteDecorator(Component component)
{
super(component);
}

public void operation()
{
super.operation();
newBehavior();
}

public void newBehavior()
{
System.out.println("装饰方法");
}
}

// 测试类
public static void main(String[] args)
{
Component component = new ConcreteComponent();
Component decorator = new ConcreteDecorator(component);
decorator.operation();
}

五、外观模式

外观模式:为多个复杂子系统提供一个一致的接口,而使这些子系统更加容易被访问

外观模式角色:

  • 外观角色Facade:为多个子系统对外提供一个共同的接口
  • 子系统角色SubSystem:实现系统的部分功能,客户可以通过外观角色访问它
  • 客户角色Client:通过一个外观角色访问各个子系统的功能

5.1 实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// 测试类
public class FacadePattern{
public static void main(String[] args){
Facade f = new Facade();
f.method();
}
}

// 外观类
class Facade{
private SubSystemA obj1 = new SubSystemA();
private SubSystemB obj2 = new SubSystemB();
private SubSystemC obj3 = new SubSystemC();

public void method(){
obj1.method1();
obj2.method2();
obj3.method3();
}
}

// 子系统A
class SubSystemA{
public void method1(){
System.out.println("子系统A的method1()方法被调用");
}
}

// 子系统B
class SubSystemB{
public void method2(){
System.out.println("子系统B的method2()方法被调用");
}
}

// 子系统C
class SubSystemC{
public void method3(){
System.out.println("子系统C的method3()方法被调用");
}
}

5.2 应用

六、享元模式

意图:运用共享技术有效地支持大量细粒度的对象。

主要解决:在有大量对象时,有可能会造成内存溢出,我们把其中共同的部分抽象出来,如果有相同的业务请求,直接返回在内存中已有的对象,避免重新创建。

何时使用: 1、系统中有大量对象。 2、这些对象消耗大量内存。 3、这些对象的状态大部分可以外部化。 4、这些对象可以按照内蕴状态分为很多组,当把外蕴对象从对象中剔除出来时,每一组对象都可以用一个对象来代替。 5、系统不依赖于这些对象身份,这些对象是不可分辨的。

主要角色

  • 抽象享元角色Flyweight:是所有的具体享元类的基类,为具体享元规范需要实现的公共接口,非享元的外部状态以参数的形式通过方法传入。
  • 具体享元角色ConcreteFlyweight:实现抽象享元角色中所规定的接口
  • 非享元角色UnsharedConcreteFlyweight:是不可以共享的外部状态 ,它以参数的形式注入具体享元的相关方法中
  • 享元工厂角色FlyweightFactory负责创建和管理享元角色。当客户对象请求享元对象时享元工厂检查系统中是否存在符合要求的享元对象如果存在提供给客户;如果不存在的话,则建一个新的享元对象。

6.1 实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
// 测试类
public class Client{
public static void main(String[] args){
FlyweightFactory factory = new FlyweightFactory();
Flyweight f01 = factory.getFlyweight("a");
Flyweight f02 = factory.getFlyweight("a");
Flyweight f03 = factory.getFlyweight("a");
Flyweight f11 = factory.getFlyweight("b");
Flyweight f12 = factory.getFlyweight("b");

f01.operation(new UnsharedConcreteFlyweight("第1次调用a"));
f02.operation(new UnsharedConcreteFlyweight("第2次调用a"));
f03.operation(new UnsharedConcreteFlyweight("第3次调用a"));
f11.operation(new UnsharedConcreteFlyweight("第1次调用b"));
f12.operation(new UnsharedConcreteFlyweight("第2次调用b"));
}
}

// 抽象享元角色
interface Flyweight{
void operation(UnsharedConcreteFlyweight state);
}

// 非享元角色
class UnsharedConcreteFlyweight state{
private String info;
UnsharedConcreteFlyweight(String info){
this.info = info;
}
public String getInfo(){
return this.info;
}
public void setInfo(String info){
this.info = info;
}
}

// 具体享元角色
class ConcreteFlyweight implement Flyweight{
private String key;
ConcreteFlyweight(String key){
this.key = key;
System.out.println("具体享元"+key+"被创建!");
}

public void operation(UnsharedConcreteFlyweight outState){
System.out.println("具体享元"+key+"被调用!");
System.out.println("非享元信息是:"+outState.getInfo());
}
}

// 享元工厂
class FlyweightFactory{
private HashMap<String,Flyweight> flyweights = new HashMap<String,Flyweight>();
public Flyweight getFlyweight(String key){
Flyweight flyweight = (Flyweight)flyweights.get(key);
if(flyweight != null){
System.out.println("具体享元"+key+"已经存在,被成功获取");
}else{
flyweight = new ConcreteFlyweight(key);
flyweights.put(key,flyweight);
}
return flyweight;
}
}

6.2 应用

七、组合模式

组合模式角色:有时又叫作部分整体模式它是一种将对象组合成树状的层次结构的模式 用来表示部分整体”的关系,使用户对单个对象和组合对象具有一致的访问性。

组合模式的角色:

  • 抽象构建角色Component:它的主要作用是为树叶构件和树枝构件声明公共接口
  • 树叶构建角色Leaf::是组合中的叶节点对象,它没有子节点,用于实现抽象构件角色中声明的公共接口。
  • 树枝构件角色Composite:是组合中的分支节点对象,它有子节点。,它的主要作用是存储和管理子部件

组合模式分为透明式的组合模式安全式的组合模式

  • 透明方式:抽象构件声明了所有子类中的全部方法,所以客户端无须区别树叶对象和树枝对象
  • 安全方式:将管理子构件的方法移到树枝构件中

7.1 实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
public class Client{
public static void main(String[] args){
Component c0 = new Composite();
Component c1 = new Composite();
Component leaf1 = new Leaf("1");
Component leaf2 = new Leaf("2");
Component leaf3 = new Leaf("3");
c0.add(leaf1);
c0.add(c1);
c1.add(leaf2);
c1.add(leaf3);
c0.operation();
}
}

// 抽象构件
interface Component{
public void add(Component c);
public void remove(Component c);
public Component getChild(int i);
public void operation();
}


// 树叶构建
class Leaf implements Component{
private String name;
public Leaf(String name){
this.name = name;
}
public void add(Component c){}
public void remove(Component c){}
public Component getChild(int i){return null;}
public void operation(){
System.out.println("树叶"+name+":被访问!");
}
}

// 树枝构件
class Composite implements Component{
private ArrayList<Component> children = new ArrayList<Component>();
public void add(Component c){
children.add(c);
}
public void remove(Component c){
children.remove(c);
}
public Component getChild(int i){
return children.get(i);
}
public void operation(){
for(Object obj:children){
((Component)obj).operation();
}
}
}

/*
执行结果:
树叶1:被访问!
树叶2:被访问!
树叶3:被访问!
*/

7.2 应用