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

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

适配器模式(Adapter)

将某个类的接口转换成客户端期望的另一个接口表示,目的是消除由于接口不匹配所造成的类的兼容性问题。

有一个Source类,拥有一个方法,待适配,目标接口时Targetable,通过Adapter类,将Source的功能扩展到Targetable里。

主要分成三类:类的适配器模式、对象的适配器模式、接口的适配器模式。

类的适配器模式

当希望将一个类转换成满足另一个新接口的类时,可以使用类的适配器模式,创建一个新类,继承原有的类,实现新的接口即可。

原有类:

package Adapter;

 

public class Original {

    public void originalMethod(){

        System.out.println("original...");

    }

}

 

接口:

package Adapter;

 

public interface ClassAdapterInterface {

    public void originalMethod();

   

    public void newMethod();

   

}

 

新类:

package Adapter;

 

public class ClassAdapter extends Original implements ClassAdapterInterface {

    @Override

    public void newMethod() {

        // TODO Auto-generated method stub

        System.out.println("new...");

    }

}

 

 

测试类:

package Adapter;

 

public class Client {

 

    /**

     * @param args

     */

    public static void main(String[] args) {

        // TODO Auto-generated method stub

        ClassAdapter ca = new ClassAdapter();

        ca.originalMethod();

        ca.newMethod();

    }

}

 

对象的适配模式

当希望将一个对象转换成满足另一个新接口的对象时,可以创建一个Adapter类,持有原类的一个实例,在Adapter类的方法中,调用实例的方法就行。

新类:

package Adapter;

 

public class ObjectAdapter implements AdapterInterface {

    private Original original;

   

    ObjectAdapter(Original original){

        super();

        this.original = original;

       

    }

   

    @Override

    public void originalMethod() {

        // TODO Auto-generated method stub

        original.originalMethod();

 

    }

 

    @Override

    public void newMethod() {

        // TODO Auto-generated method stub

        System.out.println("new");

 

    }

 

}

 

 

测试类:

package Adapter;

 

public class Client {

 

    /**

     * @param args

     */

    public static void main(String[] args) {

        Original original = new Original();

        ObjectAdapter oa = new ObjectAdapter(original);

        oa.originalMethod();

        oa.newMethod();

    }

}

 

接口的适配器模式

当不希望实现一个接口中所有的方法时,可以创建一个抽象类Adapter实现所有方法,我们写别的类的时候,继承抽象类即可。

接口:

package Adapter;

 

public interface AdapterInterface {

    public void originalMethod();

   

    public void newMethod();

   

}

 

 

抽象类:

package Adapter;

 

public abstract class Adapter implements AdapterInterface {

 

    @Override

    public void originalMethod() {

        // TODO Auto-generated method stub

 

    }

 

    @Override

    public void newMethod() {

        // TODO Auto-generated method stub

 

    }

 

}

 

 

实现类:

// InterfaceAdapter1

package Adapter;

 

public class InterfaceAdapter1 extends Adapter{

    public void newMethod() {

        // TODO Auto-generated method stub

        System.out.println("new...");

    }

}

 

// InterfaceAdapter2

package Adapter;

 

public class InterfaceAdapter2 extends Adapter{

    public void originalMethod() {

        // TODO Auto-generated method stub

        System.out.println("original...");

    }

}

 

 

测试类:

package Adapter;

 

public class Client {

 

    /**

     * @param args

     */

    public static void main(String[] args) {

       

        InterfaceAdapter1 ia = new InterfaceAdapter1();

        ia.originalMethod();

        ia.newMethod();

    }

}

 

桥接模式(Bridge)

把事物和其具体实现分开(抽象化与实现化解耦),使他们可以各自独立的变化。

接口:

package Bridge;

 

public interface Sourcable {

    public void method();

}

 

 

实现类:

// SourceSub1

package Bridge;

 

public class SourceSub1 implements Sourcable {

 

    @Override

    public void method() {

        // TODO Auto-generated method stub

        System.out.println("1...");

    }

 

}

 

// SourceSub2

package Bridge;

 

public class SourceSub2 implements Sourcable {

 

    @Override

    public void method() {

        // TODO Auto-generated method stub

        System.out.println("2...");

    }

 

}

 

 

桥:

package Bridge;

 

public abstract class Bridge   {

   

    public abstract void bridge(Sourcable Source);

   

}

 

 

桥的实现:

// Action1

package Bridge;

 

public class Action1 extends Bridge {

 

    @Override

    public void bridge(Sourcable Source) {

        // TODO Auto-generated method stub

        System.out.println("a1...");

        Source.method();

    }

 

}

// Action2

package Bridge;

 

public class Action2 extends Bridge {

 

    @Override

    public void bridge(Sourcable Source) {

        // TODO Auto-generated method stub

        System.out.println("a2...");

        Source.method();

    }

 

}

 

 

测试类:

package Bridge;

 

public class Client {

 

    /**

     * @param args

     */

    public static void main(String[] args) {

        // TODO Auto-generated method stub

        Action1 a1= new Action1();

        a1.bridge(new SourceSub1());

        a1.bridge(new SourceSub2());

       

        Action2 a2= new Action2();

        a2.bridge(new SourceSub1());

        a2.bridge(new SourceSub2());

    }

 

}

 

总结

将抽象化与实现化解耦,使得二者可以独立变化。

假设你的电脑是双系统(WinXP、Win7),而且都安装了mysql、oracle、sqlserver、DB2这4种数据库,那么你有2*4种选择去连接数据库。按平常的写法,咱要写2*4个类,但是使用了桥接模式,你只需写2+4个类,可以看出桥接模式其实就是一种将N*M转化成N+M组合的思想。(middleware的思想)

合成模式(Composite)

将多个对象组合在一起进行操作,常用于表示树形结构中,例如二叉树,数等。

树类:

package Composite;

 

import java.util.ArrayList;

import java.util.List;

 

public class TreeNode {

    private String name;

    private TreeNode parent;

    private List<TreeNode> children = new ArrayList<TreeNode>();

   

    public TreeNode(String name){

        this.name = name;

    }

   

    public String getName(){

        return name;

    }

    public void setName(String name){

        this.name = name;

    }

    public TreeNode getParent(){

        return this.parent;

    }

    public void setParent(TreeNode parent){

        this.parent = parent;

    }

    public List<TreeNode> getChildren(){

        return this.children;

    }

    public void addChild(TreeNode child){

        this.children.add(child);

    }

    public void removeChild(TreeNode child){

        this.children.remove(child);

    }

}

 

 

测试类:

package Composite;

 

public class Client {

 

    /**

     * @param args

     */

    public static void main(String[] args) {

        // TODO Auto-generated method stub

        TreeNode a = new TreeNode("a");

        TreeNode b = new TreeNode("b");

        TreeNode c = new TreeNode("c");

        TreeNode d = new TreeNode("d");

       

        a.addChild(b);

        a.addChild(c);

        a.setParent(d);

       

        System.out.println(a.getParent().getName());

        for(TreeNode t : a.getChildren()){

            System.out.println(t.getName());

        }

    }

 

}

 

装饰模式(Decorator)

动态地将责任附加到对象上,若要扩展功能,装饰者提供了比继承更具有弹性的替代方案。对于装饰者模式。

接口:

package Decorator;

 

public interface Sourcable {

    public void method();

}

 

 

原有类:

package Decorator;

 

public class Source implements Sourcable {

 

    @Override

    public void method() {

        // TODO Auto-generated method stub

        System.out.println("source...");

    }

 

}

 

 

包装类:

package Decorator;

 

public class Decorator implements Sourcable {

   

    private Source source;

   

    public Decorator(Source source){

        this.source = source;

    }

    @Override

    public void method() {

        // TODO Auto-generated method stub

        System.out.println("1 decorator...");

        source.method();

        System.out.println("2 decorator...");

    }

 

}

 

 

测试类:

package Decorator;

 

public class Client {

 

    /**

     * @param args

     */

    public static void main(String[] args) {

        // TODO Auto-generated method stub

        Source s = new Source();

        Decorator d = new Decorator(s);

        d.method();

    }

 

}

 

应用场景

1、需要扩展一个类的功能。

2、动态的为一个对象增加功能,而且还能动态撤销。(继承不能做到这一点,继承的功能是静态的,不能动态增删。)

缺点:产生过多相似的对象,不易排错!

外观模式(Facade)

将一个系统划分成若干个子系统有利于降低系统的复杂性。一个常见的设计目标是使子系统间的通信和相互依赖关系达到最小。外观模式通过引入一个外观对象,为子系统中较一般的设施提供了一个单一而简单的界面。

//子系统1

package Facade;

 

public class CPU {

    public void startup(){

        System.out.println("CPU startup...");

    }

    public void shutdown(){

        System.out.println("CPU shutdown...");

    }

}

//子系统2

package Facade;

 

public class Disk {

    public void startup(){

        System.out.println("Disk startup...");

    }

    public void shutdown(){

        System.out.println("Disk shutdown...");

    }

}

 

 

//外观类

package Facade;

 

public class Facade {

    private CPU c;

    private Disk d;

   

    public Facade(){

        this.c = new CPU();

        this.d = new Disk();

    }

   

    public void startup(){

        c.startup();

        d.startup();

        System.out.println("Facade startup...");

    }

    public void shutdown(){

        c.shutdown();

        d.shutdown();

        System.out.println("Facade shutdown...");

    }

}

 

 

//测试类

package Facade;

 

public class Client {

 

    /**

     * @param args

     */

    public static void main(String[] args) {

        // TODO Auto-generated method stub

        Facade f = new Facade();

        f.startup();

        f.shutdown();

    }

 

}

 

享元模式(Flyweight)

主要目的是实现对象的共享,即共享池,当系统中对象多的时候可以减少内存的开销,通常与工厂模式一起使用。。在某种程度上,你可以把单例看成是享元的一种特例。

//共享对象,抽象类

package FlyWeight;

 

public abstract class FlyWeight {

    public abstract void method();

}

 

 

//共享对象,实现类

package FlyWeight;

 

public class SubFlyWeight extends FlyWeight {

    private String key;

   

    public SubFlyWeight(String key){

        this.key = key;

    }

   

    @Override

    public void method() {

        // TODO Auto-generated method stub

        System.out.println("String:" + this.key);

    }

 

}

 

 

//生产共享对象工厂

package FlyWeight;

 

import java.util.HashMap;

import java.util.Map;

 

public class FlyWeightFactory {

    private Map<String, FlyWeight> map = new HashMap<String, FlyWeight>();

   

    public FlyWeight getFlyWeight(String key){

        FlyWeight fw = map.get(key);

        if(fw == null){

            fw = new SubFlyWeight(key);

            map.put(key, fw);

        }

        return fw;

    }

   

    public int getCount(){

        return map.size();

    }

}

 

 

//测试类

package FlyWeight;

 

public class Client {

 

    /**

     * @param args

     */

    public static void main(String[] args) {

        // TODO Auto-generated method stub

        FlyWeightFactory fwf = new FlyWeightFactory();

        FlyWeight fw1 = fwf.getFlyWeight("aaa");

        FlyWeight fw2 = fwf.getFlyWeight("aaa");

       

        System.out.println(fw1 == fw2);

        fw1.method();

        fw2.method();  

       

        FlyWeight fw3 = fwf.getFlyWeight("bbb");

        System.out.println(fw1 == fw3);

        fw1.method();

        fw3.method();

    }

 

}

 

代理模式(Proxy)

代理模式就是多一个代理类出来,替原对象进行一些操作。

//接口

package Proxy;

 

public interface Sourcable {

    public void method();

}

 

 

//原有类

package Proxy;

 

public class Source implements Sourcable {

 

    @Override

    public void method() {

        // TODO Auto-generated method stub

        System.out.println("source...");

    }

 

}

 

 

//代理类

package Proxy;

 

public class Proxy implements Sourcable {

    private Source s;

   

    public Proxy(){

        super();

        s = new Source();

    }

    @Override

    public void method() {

        // TODO Auto-generated method stub

        System.out.println("Proxy...");

        s.method();

    }

 

}

 

 

//测试类

package Proxy;

 

public class Client {

 

    /**

     * @param args

     */

    public static void main(String[] args) {

        // TODO Auto-generated method stub

        Sourcable p = new Proxy();

        p.method();

    }

 

}

应用场景

如果已有的方法在使用的时候需要对原有的方法进行改进,此时有两种办法:

1、修改原有的方法来适应。这样违反了“对扩展开放,对修改关闭”的原则。

2、就是采用一个代理类调用原有的方法,且对产生的结果进行控制。这种方法就是代理模式。

使用代理模式,可以将功能划分的更加清晰,有助于后期维护!

总结

Adapter, Bridge, Facade

Adapter主要是为了解决两个已有的接口之间不匹配的问题。它不考虑这些接口是怎么实现的,也不考虑它们各自可能会如何演化。这种方式不需要对两个独立设计的类中的任何一个进行重新设计,就能够使它们协同合作。当发现两个不兼容的类必须同时工作时,就需要使用Adapter模式,其目的一般是为了避免代码重复。

Bridge对抽象接口和它的实现部分进行桥接。虽然这一模式允许修改实现它的类,它仍然为用户提供一个稳定的接口。Bridge的使用者必须事先知道:一个抽象加盖有多个实现部分,并且抽象和实现两者之间独立演化。

Façade定义一个新的接口,而Adapter则复用原有接口。

Composite, Decorator, Proxy

Composite和Decorator都基于递归组合来组织可变数目的对象。

Decorator旨在使你能够不需要生成子类即可给对象添加职责。避免了静态实现所有功能的组合。

Composite旨在构造类,是多个相关的对象能够以统一的方式处理,而多重对象可以被当做一个对象来处理。

Proxy通Decorator一样,描述了怎样为对象提供一定程度上的间接引用,对象的实现部分都保留了指向另一个对象的指针,它们向这个对象发送请求。但是,Proxy不能动态地添加或分离性质,它也不是为递归组合而设计的。它的目的是,当直接访问一个实体不方便或不符合需要时,为这个实体提供一个替代者。

在Proxy中,实体定义了关键功能,而Proxy提供对它的访问。

在Decorator中,组件仅提供了部分功能,而一个或者多个Decorator负责完成其他功能。

Reference

设计模式:可复用面向对象软件的基础

转载于:https://www.cnblogs.com/SailorXun/p/4274669.html

你可能感兴趣的文章
poj 3277 City Horizon
查看>>
Hbase设置多个hmaster
查看>>
js 封装获取元素的第一个元素
查看>>
PHP 获取url里文件的扩展名
查看>>
微信API demo
查看>>
iOS 获取Home键指纹验证
查看>>
安装java8
查看>>
例说Linux内核链表(三)
查看>>
UVA 427 The Tower of Babylon 巴比伦塔(dp)
查看>>
flex布局中 width 和 flex-basis到底听谁的?
查看>>
30 Java语言基础循环结构概述和for语句的格式及其使用
查看>>
Python-Mac 安装 PyQt4
查看>>
linux命令_文件管理_pwd_打印当前目录
查看>>
am335x Linux kernel DTS pinmux 定义记录
查看>>
Linux kernel 找到gpio被占用位置
查看>>
eclipse+minGW 调试ffmpeg错误:No symbol table is loaded. Use the "file" command.
查看>>
软件测试模型汇总-V模型,W模型,X模型,H模型
查看>>
分享一个好用的函数吧,将js中的对象转成url参数
查看>>
[BZOJ] 3631: [JLOI2014]松鼠的新家
查看>>
三星内存参数含义
查看>>