Android技术知识Android开发经验谈Java设计模式

设计模式:(三)结构性模式

2018-11-05  本文已影响20人  小村医
结构性模式.png

一、适配器模式

适配器模式.png

下面来看看适配器的三个角色:

通用代码实现

目标角色

public interface Target {
    //目标角色自有的方法
    public void request();
}
public class ConcreteTarget implements Target {
    public void request (){
    
    }
}

目标角色是一个已经正式运行的角色,不可能去修改角色中的方法。

源角色

public class Adaptee {
    //原有的业务逻辑
    public void doSomething(){
    
    }
}

适配器角色

public class Adapter extends Adaptee implements Target {
    public void reqest(){
        super.doSmothing();
    }
} 

二、桥接模式

桥接模式.png

桥接模式将继承模式转化成关联关系,他降低了类与类之间的耦合度,减少了系统中类的数量,也减少了代码量。

桥接是一个接口,它与一方应该是绑定的,也就是解耦的双方中的一方必然是继承这个接口的,这一方就是实现方,而另一方正是要与这一方解耦的抽象方,如果不采用桥接模式,一般我们的处理方式是直接使用继承来实现,这样双方之间处于强链接,类之间关联性极强,如要进行扩展,必然导致类结构急剧膨胀。

uml.png

三、组合模式

组合模式.png

组合模式,就是在一个对象中包含其他对象,这些被包含的对象可能是终点对象(不再包含别的对象),也有可能是非终点对象(其内部还包含其他对象,或叫组对象),我们将对象称为节点,即一个根节点包含许多子节点,这些子节点有的不再包含子节点,而有的仍然包含子节点,以此类推


组合模式类图
public abstract class Component {
     //个体和整体都具有的共享
    public void doSomething(){
             //编写业务逻辑
     }
}
/**
  *树枝构件
  */
public class Composite extends Component {
     //构件容器
     private ArrayList<Component> componentArrayList = new ArrayList<Component>();
     //增加一个叶子构件或树枝构件
     public void add(Component component){
             this.componentArrayList.add(component);
     }
     //删除一个叶子构件或树枝构件
     public void remove(Component component){
             this.componentArrayList.remove(component);
     }
     //获得分支下的所有叶子构件和树枝构件
     public ArrayList<Component> getChildren(){
             return this.componentArrayList;
     }
}
//树叶节点是没有子下级对象的对象,定义参加组合的原始对象行为,其通用源代码
public class Leaf extends Component {
     /*
      * 可以覆写父类方法
      * public void doSomething(){
      * 
      * }
      */
}

四、装饰器模式

装饰器模式.png

装饰模式通用类图如下所示:


2018-11-13 下午5.12.56.png

在类图中,有四个角色需要说明:

//抽象构件
public abstract class Component {
     //抽象的方法
     public abstract void operate();
}

//具体构件
public class ConcreteComponent extends Component {
     //具体实现
     @Override
     public void operate() {
             System.out.println("do Something");
     }
}

//抽象装饰者
public abstract class Decorator extends Component {
     private Component component = null;        
     //通过构造函数传递被修饰者
     public Decorator(Component _component){
             this.component = _component;
     }
     //委托给被修饰者执行
     @Override
     public void operate() {
             this.component.operate();
     }
}
//具体的装饰类
public class ConcreteDecorator1 extends Decorator {
     //定义被修饰者
     public ConcreteDecorator1(Component _component){
             super(_component);
     }
     //定义自己的修饰方法
     private void method1(){
             System.out.println("method1 修饰");
     }
     //重写父类的Operation方法
     public void operate(){
             this.method1();
             super.operate();
     }
}
public class ConcreteDecorator2 extends Decorator {
     //定义被修饰者
     public ConcreteDecorator2(Component _component){
             super(_component);
     }
     //定义自己的修饰方法
     private void method1(){
             System.out.println("method1 修饰");
     }
     //重写父类的Operation方法
     public void operate(){
             this.method1();
             super.operate();
     }
}

五、外观模式

外观模式.png

也就是提供一个访问子系统的接口,除了这个接口不允许有任何访问子系统的行为发生,其通用类图如下:


外观模式类图.jpeg
// 子系统
public class ClassA {
     public void doSomethingA(){
             //业务逻辑
     }
}
public class ClassB {
     
     public void doSomethingB(){
             //业务逻辑
     }
}
public class ClassC {
     
     public void doSomethingC(){
             //业务逻辑
     }
}

//门面对象
public class Facade {
     //被委托的对象
     private ClassA a = new ClassA();
     private ClassB b = new ClassB();
     private ClassC c = new ClassC();
     //提供给外部访问的方法
     public void methodA(){
         this.a.doSomethingA();
     }
     
     public void methodB(){
         this.b.doSomethingB();
     }
     
     public void methodC(){
         this.c.doSomethingC();
     }
}

六、享元模式

享元模式.png

要求细粒度对象,那么不可避免地使得对象数量多且性质相近,那我们就将这些对象的信息分为两个部分:内部状态(intrinsic)与外部状态(extrinsic)。
● 内部状态
内部状态是对象可共享出来的信息,存储在享元对象内部并且不会随环境改变而改变,如id、name等,它们可以作为一个对象的动态附加信息,不必直接储存在具体某个对象中,属于可以共享的部分。

● 外部状态
外部状态是对象得以依赖的一个标记,是随环境改变而改变的、不可以共享的状态


享元模式类图.jpeg
//抽象享元角色
public abstract class Flyweight {
     //内部状态
     private String intrinsic;
     //外部状态
     protected final String Extrinsic;
     //要求享元角色必须接受外部状态
     public Flyweight(String _Extrinsic){
             this.Extrinsic = _Extrinsic;
     }
     //定义业务操作
     public abstract void operate();
     //内部状态的getter/setter
     public String getIntrinsic() {
             return intrinsic;
     }
     public void setIntrinsic(String intrinsic) {
             this.intrinsic = intrinsic;
     }
}

//具体享元角色。实现自己的业务逻辑,然后接收外部状态,以便内部业务逻辑对外部状态的依赖。
//注意,我们在抽象享元中对外部状态加上了final关键字,
//防止意外产生,什么意外?获得了一个外部状态,然后无意修改了一下,池就混乱了
public class ConcreteFlyweight1 extends Flyweight{
     //接受外部状态
     public ConcreteFlyweight1(String _Extrinsic){
             super(_Extrinsic);
     }
     //根据外部状态进行逻辑处理
     public void operate(){
             //业务逻辑
     }
}
public class ConcreteFlyweight2 extends Flyweight{
     //接受外部状态
     public ConcreteFlyweight2(String _Extrinsic){
             super(_Extrinsic);
     }
     //根据外部状态进行逻辑处理
     public void operate(){
             //业务逻辑
     }
}

//享元工厂
public class FlyweightFactory {
     //定义一个池容器
     private static  HashMap<String,Flyweight> pool= new HashMap<String,Flyweight>();
     //享元工厂
     public static Flyweight getFlyweight(String Extrinsic){
             //需要返回的对象
             Flyweight flyweight = null;
             //在池中没有该对象
             if(pool.containsKey(Extrinsic)){
                     flyweight = pool.get(Extrinsic);
             }else{
                     //根据外部状态创建享元对象
                     flyweight = new ConcreteFlyweight1(Extrinsic);
                     //放置到池中
                     pool.put(Extrinsic, flyweight);
             }
             return flyweight;
     }
}

七、代理模式

代理模式.png

代理模式通用类图:


代理模式类图.jpeg
//抽象主题类
public interface Subject {
     //定义一个方法
     public void request();
}

//真实主题类
public class RealSubject implements Subject {
     //实现方法
     public void request() {
             //业务逻辑处理
     }
}

//代理类
public class Proxy implements Subject {
     //要代理哪个实现类
     private Subject subject = null;    
     //默认被代理者
     public Proxy(){
             this.subject = new Proxy();
     }
     //通过构造函数传递代理者
     public Proxy(Object...objects ){
     }
     //实现接口中定义的方法
     public void request() {
             this.before();
             this.subject.request();
             this.after();
     }
     //预处理
     private void before(){
             //do something
     }
     //善后处理
     private void after(){
             //do something
     }
}

JDK 自带的动态代理:
java.lang.reflect.Proxy:生成动态代理类和对象;
java.lang.reflect.InvocationHandler(处理器接口):可以通过invoke方法实现
对真实角色的代理访问。
每次通过 Proxy 生成的代理类对象都要指定对应的处理器对象。

  1. 接口:Subject.java
public interface Subject {
    public String speak();
}
  1. 真实对象:RealSubject.java
public class RealSubject implements Subject{
  
    @Override
    public String speak() {
        System.out.println("speak");
        return "speak";
    }
}
  1. 处理器对象:MyInvocationHandler.java
public class MyInvocationHandler implements InvocationHandler {
    /**
     * 因为需要处理真实角色,所以要把真实角色传进来
     */
    Subject realSubject ;

    public MyInvocationHandler(Subject realSubject) {
        this.realSubject = realSubject;
    }

    /**
     *
     * @param proxy    代理类
     * @param method    正在调用的方法
     * @param args      方法的参数
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("调用代理类");
        if(method.getName().equals("speak")){
             String str = (String)method.invoke(realSubject, args);
            System.out.println("调用的是说话的方法");
            return str ;
        }
    }
}
  1. 调用端:Main.java
public static void main(String[] args) {
        //真实对象
        Subject realSubject =  new RealSubject();

        MyInvocationHandler myInvocationHandler = new MyInvocationHandler(realSubject);
        //代理对象
        Subject proxyClass = (Subject) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), 
          new Class[]{Subject.class}, myInvocationHandler);

       
        proxyClass.speak();
    }
上一篇 下一篇

猜你喜欢

热点阅读