设计模式三:适配器,桥接,组合,装饰,外观,享元,代理

复习一下,之前说的都是创建型模式

有工厂三家族,简单工厂,工厂方法,抽象工厂

简单工厂是一个作坊里产一款产品

工厂方法是一个大作坊有几个小作坊,每个小作坊产一款产品

抽象工厂是一个大作坊有几个小作坊,每个小作坊产不同系列的一部分。最后产一系列的产品

建造者是老板管搞论文的和搞工程的,搞工程的就是几个架构搭建,搞论文的就是搞些公式和结果图搞,最后来到实验室找到老板就知道实验室有什么东西了

享元是简历复制。把要改的改了。争取共享一些东西。

单例就是一个家庭只能生一个孩子。没有的时候创建一个,有了的话,你来我家查孩子,就带你找那个独苗。数据库里面建立连接,就是这种模式的体现。

 

以上粗俗的话主要为了方便理解和回忆,请勿当真。。。。

推荐一下个人GitHub,里面有设计模式的源码  https://github.com/tori22/DesignPattern

(竟然是HTTPS协议的)

 

今天学习结构型模式

一.适配器

将一个类的接口转换成客户希望的另外一个接口。适配器模式使得原本由于

接口不兼容而不能一起工作的那些类可以一起工作。

优点:

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

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

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

一个对象适配器可以把多个不同的适配者类适配到同一个目标,也就是说,

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

缺点:

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

适用场景:

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

想要建立一个可以重用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作。

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

旧的系统开发的类已经实现了一些功能,但是客户端却只能以另外接口的形式访问,

但我们不希望手动更改原有类的时候。

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

package AdapterPattern;

public class Adaptee {

    public void specificRequest() {
        System.out.println("特殊请求!");
    }
}
package AdapterPattern;

public class Adapter extends Target {
    private Adaptee adaptee = new Adaptee();

    @Override
    public void request() {
        adaptee.specificRequest();
    }
}
package AdapterPattern;

public class Client {
    public static void main(String[] args) {
        Target target = new Adapter();
        target.request();
    }
}
package AdapterPattern;

public class Target {
    public void request() {
        System.out.println("普通请求");
    }
}

 

二.桥接

将抽象不笨与它的实现部分分离,使它们都可以独立地变化.

桥接模式的使用场景:

1、当一个对象有多个变化因素的时候,通过抽象这些变化因素,将依赖具体实现,修改为依赖抽象。

2、当某个变化因素在多个对象中共享时。我们可以抽象出这个变化因素,然后实现这些不同的变化因素。

3、当我们期望一个对象的多个变化因素可以动态的变化,而且不影响客户的程序的使用时。

8.组合(合成):

将对象组合成树形结构以表示‘部分-整体’的层次结构,组合模式使得用户

对单个对象和组合对象的使用具有一致性。

使用场景:

当发现需求中是体现部分与整体层次结构时,以及你希望用户可以忽略组合对象与单个对象的不同,

统一地使用组合结构中的所有对象时,就应该考虑组合模式了。

package BridgePattern;

public class Abstraction {
    protected Implementor mImplementor;

    public void setImplementor(Implementor implementor) {
        mImplementor = implementor;
    }
    public void operation() {
        mImplementor.operation();
    }
}
package BridgePattern;

public class Client {

    public static void main(String[] args) {
        Abstraction ab = new RefinedAbstraction();

        ab.setImplementor(new ConcrateImplementorA());
        ab.operation();

        ab.setImplementor(new ConcrateImplementorB());
        ab.operation();
    }
}
package BridgePattern;

public class ConcrateImplementorA extends Implementor {
    @Override
    public void operation() {
        System.out.println("具体实现A的方法执行");
    }
}
package BridgePattern;

public class ConcrateImplementorB extends Implementor {
    @Override
    public void operation() {
        System.out.println("具体实现B的方法执行");
    }
}
package BridgePattern;

public abstract class Implementor {
    public abstract void operation();
}
package BridgePattern;

public class RefinedAbstraction extends Abstraction {
    @Override
    public void operation() {
        mImplementor.operation();
    }
}

 

三.组合

package CompositePattern;

public class Client {

    public static void main(String[] args) {
        Composite root = new Composite("root");
        root.add(new Leaf("Leaf A"));
        root.add(new Leaf("Leaf B"));

        Composite comp = new Composite("Composite X");
        comp.add(new Leaf("Leaf XA"));
        comp.add(new Leaf("Leaf XB"));

        root.add(comp);

        Composite comp2 = new Composite("Composite XY");
        comp2.add(new Leaf("Leaf XYA"));
        comp2.add(new Leaf("Leaf XYB"));
        comp.add(comp2);

        root.add(new Leaf("Leaf C"));
        Leaf leaf = new Leaf("Leaf D");
        root.add(leaf);
        root.remove(leaf);

        root.display(1);

    }
}
package CompositePattern;



public abstract class Component {

    protected String mName;

    public Component(String name) {
        mName = name;
    }

    public abstract void add(Component c);
    public abstract void remove(Component c);
    public abstract void display(int depth);
}
package CompositePattern;

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

public class Composite extends Component {

    private List<Component> childern = new ArrayList<>();

    public Composite(String name) {
        super(name);
    }
    @Override
    public void add(Component c) {
        childern.add(c);
    }

    @Override
    public void remove(Component c) {
        childern.remove(c);
    }

    @Override
    public void display(int depth) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < depth ; i++) {
            sb.append("-");
        }
        System.out.println(sb.append(mName).toString());

        for (Component c:childern) {
            c.display(depth+2);
        }
    }
}
package CompositePattern;

public class Leaf extends Component{

    public Leaf(String name) {
        super(name);
    }
    @Override
    public void add(Component c) {
        System.out.println("cannot add to a leaf");
    }

    @Override
    public void remove(Component c) {
        System.out.println("cannot remove to a leaf");
    }

    @Override
    public void display(int depth) {
        StringBuilder stringBuilder = new StringBuilder();
        for (int i = 0; i < depth ; i++) {
            stringBuilder.append("-");
        }

        System.out.println(stringBuilder.append(mName).toString());
    }
}

 

四.装饰

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

1.在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。

2 处理那些可以撤消的职责。

3.当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,

为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。

另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。

package DecoratorPattern;

public abstract class Component {
    public abstract void Opeartion();
}
package DecoratorPattern;

public class ConcreateComponent extends Component {
    @Override
    public void Opeartion() {
        System.out.println("具体对象的操作");
    }
}
package DecoratorPattern;

public class ConcreateDecoratorA extends Decorator{
    public String addedState;

    @Override
    public void Opeartion() {
        super.Opeartion();
        addedState = "New State";
        System.out.println("具体装饰对象A的操作" + addedState);
    }
}
package DecoratorPattern;

public class ConcreateDecoratorB extends Decorator{


    @Override
    public void Opeartion() {
        super.Opeartion();
        addedBehavior();
        System.out.println("具体装饰对象B" );
    }

    private void addedBehavior() {

    }
}
package DecoratorPattern;

public abstract class Decorator extends Component {

    protected Component mcomponent;

    public void setcomponent(Component component) {
        mcomponent = component;
    }
    @Override
    public void Opeartion() {
        if (mcomponent != null) {
            mcomponent.Opeartion();
        }
    }
}
package DecoratorPattern;

public class Test {
    public static void main(String[] args) {
        ConcreateComponent component = new ConcreateComponent();
        ConcreateDecoratorA decoratorA = new ConcreateDecoratorA();
        ConcreateDecoratorB decoratorB = new ConcreateDecoratorB();

        decoratorA.setcomponent(component);
        decoratorB.setcomponent(decoratorA);
        decoratorB.Opeartion();
    }
}

 

五.外观

为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,

这个接口使得这一子系统更加容易使用。

适用环境:

在开发阶段,子系统往往因为不断的重构演化而变得越来越复杂,

增加外观Facade可以提供一个简单的接口,减少它们之间的依赖.

在维护一个遗留的大型系统时,可能这个系统已经非常难以维护和扩展了,可以为

新系统开发一个外观Facade类,来提供设计粗糙或高度复杂的遗留代码的比较清晰

简单的接口,让新系统与Facade对象交互,Facade与遗留代码交互所有复杂的工作。

优点:

实现了子系统与客户端之间的松耦合关系。

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

package FacedePattern;

public class Client {

    public static void main(String[] args) {
        Facede facede = new Facede();

        facede.methodA();
        facede.methodB();
    }
}
package FacedePattern;

public class Facede {
    private SubSystemOne one;
    private SubSystemTwo two;
    private SubSystemThree three;
    private SubSystemFour four;

    public Facede() {
        one = new SubSystemOne();
        two = new SubSystemTwo();
        three = new SubSystemThree();
        four = new SubSystemFour();
    }

    public void methodA() {
        System.out.println("方法组A------");
        one.methodOne();
        two.methodTwo();
        four.methodFour();
    }

    public void methodB() {
        System.out.println("方法组B----------");
        two.methodTwo();
        three.methodThree();
    }

}
package FacedePattern;

public class SubSystemFour {
    public void methodFour() {
        System.out.println("子系统方法四");
    }
}
package FacedePattern;

public class SubSystemOne {
    public void methodOne() {
        System.out.println("子系统方法一");
    }
}
package FacedePattern;

public class SubSystemThree {
    public void methodThree() {
        System.out.println("子系统方法三");
    }
}
package FacedePattern;

public class SubSystemTwo {
    public void methodTwo() {
        System.out.println("子系统方法二");
    }
}

 

六.享元

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

优点:

1、享元模式的优点在于它能够极大的减少系统中对象的个数。

2、享元模式由于使用了外部状态,外部状态相对独立,不会影响到内部状态,

所以享元模式使得享元对象能够在不同的环境被共享。

缺点

1、由于享元模式需要区分外部状态和内部状态,使得应用程序在某种程度上来说更加复杂化了。

2、为了使对象可以共享,享元模式需要将享元对象的状态外部化,而读取外部状态使得运行时间变长。

模式适用场景

1、如果一个系统中存在大量的相同或者相似的对象,由于这类对象的大量使用,会造成系统内存的耗费,

可以使用享元模式来减少系统中对象的数量。

2、对象的大部分状态都可以外部化,可以将这些外部状态传入对象中。

package FlyweightPattern;

public class Client {

    public static void main(String[] args) {
        int extrinsicstate = 22;

        FlyweightFactory factory = new FlyweightFactory();

        Flyweight fx = factory.getFlyweight("x");
        fx.operation(--extrinsicstate);

        Flyweight fy = factory.getFlyweight("y");
        fy.operation(--extrinsicstate);

        Flyweight fz = factory.getFlyweight("z");
        fz.operation(--extrinsicstate);

        Flyweight uf = new UnsharedConcreteFlyweight();
        uf.operation(--extrinsicstate);
    }
}
package FlyweightPattern;

public class ConcreteFlyweight extends Flyweight{
    @Override
    public void operation(int extrinsicstate) {
        System.out.println(String.format("具体Flyweight:%s",extrinsicstate));
    }
}
package FlyweightPattern;

public abstract class Flyweight {
    public abstract void operation(int extrinsicstate);
}
package FlyweightPattern;

import java.util.Hashtable;

public class FlyweightFactory {

    private Hashtable flyweight = new Hashtable();

    public FlyweightFactory() {
        flyweight.put("x",new ConcreteFlyweight());
        flyweight.put("y",new ConcreteFlyweight());
        flyweight.put("z",new ConcreteFlyweight());
    }

    public Flyweight getFlyweight(String key) {
        return (Flyweight)flyweight.get(key);
    }
}
package FlyweightPattern;

public class UnsharedConcreteFlyweight extends Flyweight {
    @Override
    public void operation(int extrinsicstate) {
        System.out.println(String.format("不共享的具体Flyweight:%d",extrinsicstate));
    }
}

 

七.代理

为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用

另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。

代理模式常被分为远程代理、虚拟代理、保护代理等等。

优点:

1)代理模式能将代理对象与真正被调用的对象分离,在一定程度上降低了系统的耦合度。

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

代理对象也可以对目标对象调用之前进行其他操作。

缺点:

1)在客户端和目标对象增加一个代理对象,会造成请求处理速度变慢。

2)增加了系统的复杂度。

使用场景:

1)远程代理,也就是为一个对象在不同的地址空间提供局部代表。这样可以隐藏一个对象存在于

不同地址空间的事实。

2)虚拟代理,根据需要创建开销很大的对象。通过它来存放实例化需要很长时间的对象。

3)安全代理,用来控制真实对象访问时的权限。

4)智能指引,当调用目标对象时,代理可以处理其他的一些操作。

package ProxyPattern;

public class Client {
    public static void main(String[] args) {
        Proxy proxy = new Proxy();
        proxy.request();
    }
}
package ProxyPattern;

public class Proxy extends Subject {
   private RealSubject mRealSubject;
    @Override
    public void request() {
        if (mRealSubject == null) {
            mRealSubject = new RealSubject();
        }

        mRealSubject.request();
    }
}
package ProxyPattern;

public class RealSubject extends Subject {
    @Override
    public void request() {
        System.out.println("真实请求");
    }
}
package ProxyPattern;

public abstract class Subject {
    public abstract void request();
}

 

posted on 2018-04-12 22:23  小嘤嘤  阅读(423)  评论(0编辑  收藏  举报

导航