您的位置:首页 > 编程语言 > Java开发

JAVA设计模式-3-结构型模式

2015-11-01 22:16 417 查看

适配器模式

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

uml



code

// 已存在的、具有特殊功能、但不符合我们既有的标准接口的类
class Adaptee {
public void specificRequest() {
System.out.println("被适配类具有 特殊功能...");
}
}

// 目标接口,或称为标准接口
interface Target {
public void request();
}

// 具体目标类,只提供普通功能
class ConcreteTarget implements Target {
public void request() {
System.out.println("普通类 具有 普通功能...");
}
}

// 适配器类,继承了被适配类,同时实现标准接口
class Adapter  implements Target{
Adaptee adaptee=new Adaptee();
public void request() {
adaptee.specificRequest();
}
}

// 测试类public class Client {
public static void main(String[] args) {
// 使用普通功能类
Target concreteTarget = new ConcreteTarget();
concreteTarget.request();

// 使用特殊功能类,即适配类
Target adapter = new Adapter();
adapter.request();
}
}
优点

通过适配器,客户端可以调用同一接口,因而对客户端来说是透明的。这样做更简单、更直接、更紧凑。

复用了现存的类,解决了现存类和复用环境要求不一致的问题。

目标类和适配者类解耦,通过引入一个适配器类重用现有的适配者类,而无需修改原有代码。

同一个适配器可以把适配者类和它的子类都适配到目标接口。

缺点

对于对象适配器来说,更换适配器的实现过程比较复杂。

适用场景

系统需要使用现有的类,而这些类的接口不符合系统的接口。

两个类所做的事情相同或相似,但是具有不同接口的时候。

使用第三方组件,组件接口定义和自己定义的不同,不希望修改自己的接口,但是要使用第三方组件接口的功能。

装饰模式

装饰模式(Decorator)动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更灵活。

uml



code:

public interface Component {
public void sampleOperation();
}
public class ConcreteComponent implements Component {

    @Override
    public void sampleOperation() {
        // 写相关的业务代码
    }

}
public class Decorator implements Component{
    private Component component;
    
    public Decorator(Component component){
        this.component = component;
    }
    @Override
    public void sampleOperation() {
        // 委派给构件
        component.sampleOperation();
    }
}
public class ConcreteDecoratorA extends Decorator {

    public ConcreteDecoratorA(Component component) {
        super(component);
    }
    
    @Override
    public void sampleOperation() {
     super.sampleOperation();
        // 写相关的业务代码
    }
}
public class ConcreteDecoratorB extends Decorator {

    public ConcreteDecoratorB(Component component) {
        super(component);
    }
    
    @Override
    public void sampleOperation() {
      super.sampleOperation();
        // 写相关的业务代码
    }
}
public class Test{
public static void main(String[] args){
<span style="white-space:pre">	</span>ConcreteComponent c=new ConcreteComponent();
<span style="white-space:pre">	</span>Decorator d1=new ConcreteDecoratorA(c);
<span style="white-space:pre">	</span>Decorator d2=new ConcreteDecoratorB(d2);
<span style="white-space:pre">	</span>d2.sampleOperation()
<span style="white-space:pre">	</span>}
}


优点

有效地把类的核心职责和装饰功能区分开,而且可以去除相关类中重复的装饰逻辑。

装饰模式比继承关系更为灵活。

缺点

这种比继承更加灵活机动的特性,也同时意味着更加多的复杂性。

装饰模式会导致设计中出现许多小类,如果过度使用,会使程序变得很复杂。

装饰模式是针对抽象组件(Component)类型编程。但是,如果你要针对具体组件编程时,就应该重新思考你的应用架构,以及装饰者是否合适。

使用场景

需要扩展一个类的功能,或给一个类添加附加职责。

需要动态的给一个对象添加功能,这些功能可以再动态的撤销。

需要增加由一些基本功能的排列组合而产生的非常大量的功能,从而使继承关系变的不现实。

当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。

代理模式

代理模式(Proxy)为其他对象提供一种代理以控制对这个对象的访问。

uml



code

/**
* 抽象主题,定义主要功能
*/
publicinterface Subject {
publicvoid operate();
}
/**
 * 具体主题
 */
publicclass RealSubject implements Subject{
 
   @Override
   publicvoid operate() {
        System.out.println("realsubject operatestarted......");
   }
}
/**
 * 代理类
 */
publicclass Proxy implements Subject{
 
   private Subject subject;
 
   public Proxy(Subject subject) {
        this.subject = subject;
   }
 
   @Override
   publicvoid operate() {
        System.out.println("before operate......");
        subject.operate();
        System.out.println("after operate......");
   }
}
/**
 * 客户
 */
publicclass Client {
   /**
    * @param args
    */
   public static void main(String[] args) {
        Subject subject = new RealSubject();
        Proxy proxy = new Proxy(subject);
        proxy.operate();
   }
}


优点

职责清晰

代理对象可以在客户端和目标对象之间起到中介的作用,这样起到了中介的作用和保护了目标对象的作用。

高扩展性

应用场景

远程代理

虚拟代理

安全代理

外观模式

外观模式(Facade)为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。

uml



code
class CPU {
 public void freeze() { ... }
 public void jump(long position) { ... }
 public void execute() { ... }
}
class Memory {
 public void load(long position, byte[] data) {
 ...
 }
}
class HardDrive {
 public byte[] read(long lba, int size) {
 ...
 }
}

class Computer {
 public void startComputer() {
 cpu.freeze();
 memory.load(BOOT_ADDRESS, hardDrive.read(BOOT_SECTOR, SECTOR_SIZE));
 cpu.jump(BOOT_ADDRESS);
 cpu.execute();
 }
}
/* Client */
class You {
 public static void main(String[] args) {
 Computer facade = new Computer();
 facade.startComputer();
 }
}
优点
实现了子系统与客户端之间的松耦合关系。

客户端屏蔽了子系统组件,减少了客户端所需处理的对象数目,并使得子系统使用起来更加容易。

应用场景
设计初期阶段,应该有意识的将不同层分离,层与层之间建立外观模式(比如在表示层,逻辑层,数据访问层之间做一个外观模式的封装)。

开发阶段,子系统越来越复杂,增加外观模式提供一个简单的调用接口。

维护一个大型遗留系统的时候,可能这个系统已经非常难以维护和扩展,但又包含非常重要的功能,为其开发一个外观类,以便新系统与其交互。

桥接模式

桥接模式(Bridge)将抽象部分与它的实现部分分离,使他们都可以独立地变化。

uml



code

class Abstraction {
protected Implementor implementor;

public void setImplementor(Implementor impl) {
implementor = impl;
}

public void Operation() {
implementor.Operation();
}
}

interface Implementor {
public void Operation();
}

class RefinedAbstraction extends Abstraction {
public void Operation() {
implementor.Operation();
}
}

class ConcreteImplementorA implements Implementor {
public void Operation() {
System.out.println("ConcreteImplementorA Operation");
}
}

class ConcreteImplementorB implements Implementor {
public void Operation() {
System.out.println("ConcreteImplementorB Operation");
}
}

public class Test {
public static void main(String[] args) {
Abstraction abstraction = new RefinedAbstraction();
/* Set implementation and call */
abstraction.setImplementor( new ConcreteImplementorA());
abstraction.Operation();
/* Change implemention and call */
abstraction.setImplementor(  new ConcreteImplementorB());
abstraction.Operation();
}
}
例子写的不好。

优点

将实现予以解耦,让它和界面之间不再永久绑定。

抽象和实现可以独立扩展,不会影响到对方。

对于具体实现的修改,不会影响到客户端。

缺点

增加了设计复杂度。

抽象类的修改影响到子类。

应用场景

适用在需要跨多平台的图形和窗口系统。

Bridge模式有时候类似于多继承方案,但是多继承方案往往违背了类的单一职责原则(即一个类只有一个变化的原因),复用性比较差。Bridge模式是比多继承方案更好的解决方法。

Bridge模式的应用一般在“两个非常强的变化维度”,有时候即使有两个变化的维度,但是某个方向的变化维度并不剧烈——换言之两个变化不会导致纵横交错的结果,并不一定要使用Bridge模式。

实现系统可能有多角度分类,每一种分类都有可能变化,那么就把这种多角度分离出来让他们独立变化,减少它们之间的耦合。

简单来说就是有两个以上的频繁变化的时候时候可以选择桥接模式。

组合模式

组合模式(composite)将对象组合成树形结构以表示‘部分-整体’的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。

uml



code

import java.util.ArrayList;
import java.util.List;

//抽象的部件类描述将来所有部件共有的行为
abstract class Component {
protected String name;

// 添加部件
public abstract void Add(Component component);

// 删除部件
public abstract void Remove(Component component);

// 遍历所有子部件
public abstract void eachChild();
}

// 组合部件类
class Leaf extends Component {
// 叶子节点不具备添加的能力,所以不实现
public void Add(Component component) {
throw new Exception();
}

// 叶子节点不具备添加的能力必然也不能删除
public void Remove(Component component) {
throw new Exception();
}

// 叶子节点没有子节点所以显示自己的执行结果
public void eachChild() {
System.out.println("执行了.." + name);
}
}

// 组合类
class Composite extends Component {
// 用来保存组合的部件
List<Component> myList = new ArrayList<Component>();

// 添加节点 添加部件
public void Add(Component component) {
myList.add(component);
}

// 删除节点 删除部件
public void Remove(Component component) {
myList.remove(component);
}

// 遍历子节点
public void eachChild() {
System.out.println("执行了.." + name);
for (Component c : myList) {
c.eachChild();
}
}
}

public class Test {
public static void main(String[] args) {
// 构造根节点
Composite rootComponent = new Composite();
rootComponent.name = "根节点";

// 添加两个叶子几点,也就是子部件
Leaf l1 = new Leaf();
l1.name = "叶子节点一";
Composite component = new Composite();
component.name = "二级根节点";
Leaf l2 = new Leaf();
l2.name = "叶子节点二";
component.Add(l2);
rootComponent.Add(l1);
rootComponent.Add(component);

// 遍历组合部件
rootComponent.eachChild();
}
}


应用场景

公司部门的结构

需求中是体现部分与整体层次的结构时,以及你希望用户可以忽略组合对象与单个对象的不同,统一地使用组合结构中的所有对象时,就应该考虑用组合模式。

享元模式

享元模式(Flyweight)运用共享技术有效地支持大量细粒度的对象。

uml



优点

减少内存的使用量,共享对象。

加快运行时的速度。

缺点

逻辑复杂

应用场景

线程池

如果一个应用程序使用了大量的对象,而大量的这些对象造成了很大的存储开销时就应该考虑使用

对象的大多数状态可以外部状态,如果删除对象的外部状态,那么可以用相对较少的共享对象取代很多组对象时可以考虑。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: