设计模式 GOF23 结构型

6 篇文章 0 订阅

设计模式 GOF23 提纲

设计模式 GOF23 创建型

设计模式 GOF23 结构型

设计模式 GOF23 行为型

结构型

适配器模式

场景:目标对象(Target)无法使用适配者(Adaptee),并且不能修改适配者。
实现:创建一个Adapter,继承目标对象,同时继承或者组合适配者(Adaptee)。
优缺点:
- 优点:对接的细节存在于Adapter中。当Adaptee发生变化时,改动Adapter即可。
常见实例:在utils中封装一些第三方功能
注意:分为两种方式:类适配器(继承Adaptee)、对象适配器(组合Adaptee)。
一般来说,对象适配器更灵活更常用,但是类适配器可以改写适配者的方法。

//目标对象
public interface Target{
    public void request();
}
//适配者
public class Adaptee{
    public void adapteeRequest(){
        System.out.println("this is adapteeRequest");
    }
}

//类适配器,实现目标对象,继承适配者
public class ClassAdapter extends Adaptee implements Target{
    public void request(){
        System.out.println("ClassAdapter request begin");
        super.adapteeRequest();
    }
}

//对象适配器,实现目标对象,组合适配者
public class ObjectAdapter implements Target{
    public Adaptee adaptee;
    public ObjectAdapter(Adaptee adaptee) { this.adaptee = adaptee; }
    public void request(){
        System.out.println("ObjectAdapter request begin");
        adaptee.adapteeRequest();
    }
}

//测试
public class Test {
    public static void main(String[] args) {
        Target classAdapter = new ClassAdapter();
        classAdapter.request();

        Target objectAdapter = new ObjectAdapter(new Adaptee());
        objectAdapter.request();
    }
}

桥接模式

场景:某一个类系列,具有太多维度的属性,导致类数量爆炸。
实现:一个维度定义一个抽象类,多个维度组合到一起。
对比:
- 桥接模式的维度较少、但是必须的;装饰模式的维度有很多,最终可能只选择几种;就像他们的名字,一个是桥梁,一个是装饰。
- 和builder模式对比,builder处理单个类的复杂构造,桥接通过抽象维度,防止类数量的爆炸;

//抽象类
public abstract class Computer{
    private KeyBoard keyBoard;
    private Mouse mouse;
    public Computer(KeyBoard keyBoard,Mouse mouse){
        this.keyBoard = keyBoard;
        this.mouse = mouse;
    }
    public void ShowDetail(){
        this.keyBoard.ShowKeyBoard();
        this.mouse.ShowMouse();
    }
}
//KeyBoard
public abstract class KeyBoard { public abstract void ShowKeyBoard();  }
public class GoodKeyBoard extends KeyBoard { public void ShowKeyBoard() { System.out.println("with a good KeyBoard"); } }
public class BadKeyBoard extends KeyBoard { public void ShowKeyBoard() { System.out.println("with a Bad KeyBoard"); } }
//Mouse
public abstract class Mouse{public abstract void ShowMouse(); }
public class GoodMouse extends Mouse { public void ShowMouse() { System.out.println("with a good Mouse"); } }
public class BadMouse extends Mouse { public void ShowMouse() { System.out.println("with a Bad Mouse"); } }

//组合
public class Lenovo extends Computer{}
public class Apple extends Computer{}

//应用
new Lenovo(new GoodKeyBoard(),new GoodMouse()).ShowDetail();
new Apple(new BadKeyBoard(),new GoodMouse()).ShowDetail();

组合模式

场景:在树结构中,有叶子对象(leaf)和组合对象(Composite)。为了更好的描述树结构,有必要将两种对象的处理方式统一。
实现:建立抽象概念Component,实现两者统一的处理方式。当处理两者都支持的方法时,使用Component。
常见实例:文件系统(Folder File)
特点:有点像俄罗斯套娃。

public abstract class Component{}
public class Leaf extends Component{}
public class Branch extends Component{
    private List<Component> child=new List<Component>();//这里不用关心leaf还是composite
    public void add(Component component) { this.child.add(component); }//这里不用关心leaf还是composite
    public void remove(Component component) { this.child.remove(component); }//这里不用关心leaf还是composite
}

装饰模式

场景:在抽象类时,遇到很多维度的属性,同时这些维度不是必须的。或者每个维度会导致某些方法的细微差异。
实现:在基类之上,建立一个装饰抽象类(内含基类),多个装饰具体类可以互相嵌套。
对比桥接模式:
- 桥接模式的维度基本是固定的,装饰更灵活,更随意
- 装饰除了减少类,还有一个巨大的作用,就是不断修饰同一个方法。

public class Computer{public void show() { System.out.println("this is a computer"); } }
public abstract class ComputerDecorator extends Computer{
    protected Computer computer;
    public ComputerDecorator(Computer computer){ this.computer=computer;    }
    public show() { computer.show(); }
}

public class WithKeyboardDecorator extends ComputerDecorator{
    public WithKeyboardDecorator(Computer computer){ this.computer=computer;   }
    @override
    public show() {
        computer.show();
        System.out.println("with a keyboard");
    }
}
public class WithMouseDecorator extends ComputerDecorator{
    public WithMouseDecorator(Computer computer){ this.computer=computer;   }
    @override
    public show() {
        computer.show();
        System.out.println("with a mouse");
    }
}

//高兴的话,可以配两个键盘,毕竟只是demo代码
Computer computer = new Computer();
new WithMouseDecorator(new WithKeyboardDecorator(new WithKeyboardDecorator(computer))).show();
//其实这个Computer也可以建多个子类,比如lenovo apple,那么可以:
new WithMouseDecorator(new WithKeyboardDecorator(new Apple())).show();
new WithKeyboardDecorator(new WithMouseDecorator(new Lenovo())).show();

外观模式

场景:现有子系统包含很多接口,但是Client只要几个。
实现:提供一个专门的类,将子系统封装起来,为这个client提供接口。
优点:封装了子系统的复杂性

public class System1 { public void sayHello() { } }
public class System2 { public void tellMe(){ } }
public class System3 { public void greeting(){ } }

public class FacadeController {
    private System1 system1;
    private System2 system2;
    private System3 system3;
    public FacadeController(){
        system1 = new System1();
        system2 = new System2();
        system3 = new System3();
    }
    //封装子系统的内部复杂性,统一对外提供服务
    public void do_system1(){ return system1.sayHello(); }
    public void do_system2(){ return system2.tellMe(); }
    public void do_system3(){ return system3.greeting(); }
}

享元(轻量级)模式

场景:需要使用大量的对象,这些对象相似度很高,重复使用率很高。
实现:使用一个工厂,将对象管理起来,相同的对象只要一份就可以了。
优缺点:
- 优点:节约了内存
- 缺点:需要分离这些对象的内部状态、外部状态,具有复杂度。
常见实例:JAVA的String,数据库链接池,缓存

//网抄的代码,重点就是“相同的对象只要一份就可以了”
public class ShapeFactory {
   private static final HashMap<String, Shape> circleMap = new HashMap<>();
   public static Shape getCircle(String color) {
      Circle circle = (Circle)circleMap.get(color);
      if(circle == null) {
         circle = new Circle(color);
         circleMap.put(color, circle);
         System.out.println("Creating circle of color : " + color);
      }
      return circle;
   }
}

代理模式

场景:无法访问真实对象(RealSubject),真实对象的访问开销极大;
实现:创建代理对象(Proxy),像访问真实类一样,访问代理类
优缺点:
- 优点:隐藏了真实对象
- 缺点:效率必然下降
常见实例:防火墙代理、VPN

//为保证真实类和代理类的表现一致,需要同一个基类
public interface BaseNet{public void visit();}
public class OutNet implements BaseNet {
    @override
    public void visit(){ System.out.println("net is ok"); }
}
//通过网络代理,可以访问外网
public class NetProxy implements BaseNet{
    public OutNet outnet;
    @override
    public void visit(){
        //通过真实对象,实现访问
        if (outnet==null){
            outnet = new OutNet();
        }
        outnet.visit();
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值