面试中常考的设计模式解读

5、代理模式

  Proxy模式又叫做代理模式,是构造型的色痕迹模式之一,它可以为其他对象提供一种代理(Proxy)以控制对这个对象的访问。
在这里插入图片描述
静态代理的优缺点
优点:可以做到在符合开闭原则的情况下对目标对象进行功能扩展。
缺点:我们得为每一个服务都得创建代理类,工作量太大,不易管理。同时接口一旦发生改变,代理类也得相应修改。


    public interface Person {
    void work();

    // 说明静态代理的缺点
    double getMoney();
    }

public class ManPersonProxy implements Person {

    private ManPerson p;

    public ManPersonProxy(ManPerson person){
        this.p = person;
    }

    @Override
    public void work() {
        System.out.println("上班。。。");
        if (p.getMoney() > 10000.00){
            p.work();
        }
        System.out.println("下班。。。");
    }

    @Override
    public double getMoney() {
        return 0;
    }
}

public class ManPerson implements Person {

    private double money;

    @Override
    public void work() {
        System.out.println("男生在工作。。。");
    }

    public void setMoney(double money) {
        this.money = money;
    }

    public double getMoney() {
        return money;
    }
}

public class MainClass {
    public static void main(String[] args) {
        ManPerson manPerson = new ManPerson();
        // manPerson.work();
        manPerson.setMoney(522.00);

        Person person = new ManPersonProxy(manPerson);
        person.work();

    }
}

动态代理
虽然相对于静态代理,动态代理大大减少了我们的开发任务,同时减少了对业务接口的依赖,降低了耦合度。
但是还是有一点点小小的遗憾之处,那就是它始终无法摆脱仅支持interface代理的桎梏,因为它的设计注定
了这个遗憾。回想一下那些动态生成的代理类的继承关系图,它们已经注定有一个共同的父类叫Proxy。
Java的继承机制注定了这些动态代理类们无法实现对class的动态代理,原因是多继承在Java中本质上就行不通。
有很多条理由,人们可以否定对 class代理的必要性,但是同样有一些理由,相信支持class动态代理会更美好。
接口和类的划分,本就不是很明显,只是到了Java中才变得如此的细化。如果只从方法的声明及是否被定义来
考量,有一种两者的混合体,它的名字叫抽象类。实现对抽象类的动态代理,相信也有其内在的价值。此外,
还有一些历史遗留的类,它们将因为没有实现任何接口而从此与动态代理永世无缘。如此种种,不得不说是一个
小小的遗憾。但是,不完美并不等于不伟大,伟大是一种本质,Java动态代理就是佐例。

public interface Person {
    void work();
}
public class ManPerson implements Person {

    private double money;

    @Override
    public void work() {
        System.out.println("男生在工作。。。");
    }

    public void setMoney(double money) {
        this.money = money;
    }

    public double getMoney() {
        return money;
    }
}

public class ManPersonProxy{

    private Object object;

    public ManPersonProxy(Object o){
        this.object = o;
    }

    /**
     *Object proxy:代理对象,也就是Proxy.newProxyInstance()方法返回的对象,通常我们用不上它;
     *Method method:表示当前被调用方法的反射对象,例如mi.fun1(),那么method就是fun1()方法的反射对象;
     *Object[] args:表示当前被调用方法的参数,当然mi.fun1()这个调用是没有参数的,所以args是一个零长数组。
     */
    public Object creatProxy(){
        return Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("动态代理执行。。。");
                if ("work".equals(method.getName())){
                    method.invoke(object,args);
                }
                System.out.println("动态代理执行结束。。。");
                return null;
            }
        });
    }

}

public class MainClass {
    public static void main(String[] args) {
        ManPerson manPerson = new ManPerson();
        // manPerson.work();

        ManPersonProxy manPersonProxy = new ManPersonProxy(manPerson);
        Person person = (Person) manPersonProxy.creatProxy();
        person.work();

    }
}

  代理模式啊,在生活中这样的例子随处可见,比如说,中间商,比如说房产中介,比如说媒婆。当两个人不能直接对话的时候,这个时候就需要间接的通过中间人来实现对话了。代理从字面意思上理解是代为处理,在具体的应用中,有委托类,有被代理类,委托类基本上在功能上和被代理类一样,但是有一点不同,就是委托类可以在和被代理类的基础上增加新的功能。代理分为静态代理和动态代理,静态代理,会产生冗余代码,动态代理可以很好的解决这个问题。

6、适配器模式

  Adapter模式也叫适配器模式,是构造模式之一,通过
Adapter模式可以改变已有类(或外部类)的接口形式
在这里插入图片描述
在这里插入图片描述
**1:Target(目标抽象类):**目标抽象类定义客户所需的接口,可以是一个抽象类或接口,也可以是具体类。在类适配器中,由于C#语言不支持多重继承,所以它只能是接口。
  2:Adapter(适配器类):它可以调用另一个接口,作为一个转换器,对Adaptee和Target进行适配。它是适配器模式的核心。
  3:Adaptee(适配者类):适配者即被适配的角色,它定义了一个已经存在的接口,这个接口需要适配,适配者类包好了客户希望的业务方法。
优缺点:
优点:
    1:将目标类和适配者类解耦,通过引入一个适配器类来重用现有的适配者类,无需修改原有结构。
    2:增加了类的透明性和复用性,将具体的业务实现过程封装在适配者类中,对于客户端类而言是透明的,而且提高了适配者的复用性,同一适配者类可以在多个不同的系统中复用。
    3:灵活性和扩展性都非常好,通过使用配置文件,可以很方便的更换适配器,也可以在不修改原有代码的基础上 增加新的适配器,完全复合开闭原则。
  缺点:
    1:一次最多只能适配一个适配者类,不能同时适配多个适配者。
    2:适配者类不能为最终类,在C#中不能为sealed类
    3:目标抽象类只能为接口,不能为类,其使用有一定的局限性。

public class Adapter extends Chinese{

    public void useTranslate(){
        System.out.println("使用了翻译。。。");
        this.sayChinese();
    }

}
public class Adapter2 {

    private Chinese chinese;

    public Adapter2(Chinese chinese){
        this.chinese = chinese;
    }

    public void useTranslate(){
        System.out.println("使用了翻译。。。");
        this.chinese.sayChinese();
    }
}
public class Chinese {

    public void sayChinese(){
        System.out.println("说中文。。。");
    }
}

public class MainClass {
    public static void main(String[] args) {
        Adapter adapter = new Adapter();
        adapter.useTranslate();


        Adapter2 adapter2 = new Adapter2(new Chinese());
        adapter2.useTranslate();
    }
}

  在生活中适配器模式的例子多不胜数,比如说,翻译,比如说变压器,比如说转接口,这些都是适配思想,这时你会发现适配器模式和代理模式很类似,从字面意思上理解,适配适配就是适合匹配,就是在一些不适合直接对话的时候,我们通过适配的方式可以让其对话, 适配类和被适配类功能上一样,只不过,适配类会比被适配类多一些功能。

7、观察者模式

  Observer模式是行为模式之一,它的作用是当一个对象的状态发生变化时,能够自动通知其他关联对象,自动刷新对象状态。Observer模式提供给关联对象一种同步通信的手段,使某个对象与依赖它的其他对象之间保持状态同步。
在这里插入图片描述
在这里插入图片描述
抽象被观察者角色:也就是一个抽象主题,它把所有对观察者对象的引用保存在一个集合中,每个主题都可以有任意数量的观察者。抽象主题提供一个接口,可以增加和删除观察者角色。一般用一个抽象类和接口来实现。
抽象观察者角色:为所有的具体观察者定义一个接口,在得到主题通知时更新自己。
具体被观察者角色:也就是一个具体的主题,在集体主题的内部状态改变时,所有登记过的观察者发出通知。
具体观察者角色:实现抽象观察者角色所需要的更新接口,一边使本身的状态与制图的状态相协调。
优缺点及其适应场景:
优点: 1、观察者和被观察者是抽象耦合的。 2、建立一套触发机制。
缺点: 1、如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。 2、如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。 3、观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。
使用场景
一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中使它们可以各自独立地改变和复用。
一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度。
一个对象必须通知其他对象,而并不知道这些对象是谁。
需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……,可以使用观察者模式创建一种链式触发机制。

public class Article {

    private String title;

    private String content;

    public void setContent(String content) {
        this.content = content;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getContent() {
        return content;
    }

    public String getTitle() {
        return title;
    }
}

public class BlogUser extends Observable {

    public void publishes(String title,String content){
        Article article = new Article();
        article.setTitle(title);
        article.setContent(content);
        System.out.println("博主发表了新文章,文章标题是"+title +"文章的内容是"+content);
        this.setChanged();
        this.notifyObservers(article);
    }
}

public class MyObjectServer implements Observer {

    @Override
    public void update(Observable o, Object arg) {
        Article article = (Article)arg;
        System.out.println("博主发表了新的文章:");
        System.out.println("文章标题是:"+article.getTitle());
        System.out.println("博客内容为:"+article.getContent());
    }
}

public class MainClass {
    public static void main(String[] args) {
        BlogUser blogUser = new BlogUser();
        blogUser.addObserver(new MyObjectServer());
        blogUser.publishes("这是博客的标题!","这是博客的内容!");
    }
}

  观察者模式,从字面意思上来讲,观察者,就是一种观察,注视的方式,我们通过观察来发现一些事情从而做出相应的改变,这就是观察者模式,在生活中观察者模式体现在,比如一个游戏,叫你动我猜,在编程中体现在比如在博客系统中, 别人给你点个赞,或者评论了你,那么,你会收到通知的,这个时候就可以用观察者模式来实现,一个动作因为另一个动作产生的变化而产生变化。

8、装饰模式

装饰(Decorator)模式又叫做包装模式。通过一种对客户端透明的方式来扩展对象的功能,是继承关系的一个替代方案。
在这里插入图片描述
Component为统一接口,也是装饰类和被装饰类的基本类型。
ConcreteComponent为具体实现类,也是被装饰类,他本身是个具有一些功能的完整的类。
Decorator是装饰类,实现了Component接口的同时还在内部维护了一个ConcreteComponent的实例,并可以通过构造函数初始化。而Decorator本身,通常采用默认实现,他的存在仅仅是一个声明:我要生产出一些用于装饰的子类了。而其子类才是赋有具体装饰效果的装饰产品类。
ConcreteDecorator是具体的装饰产品类,每一种装饰产品都具有特定的装饰效果。可以通过构造器声明装饰哪种类型的ConcreteComponent,从而对其进行装饰。
优缺点及其适应场景:
优点:装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。
缺点:多层装饰比较复杂。
使用场景: 1、扩展一个类的功能。 2、动态增加功能,动态撤销。

public interface Car {

    void show();

    void run();
}
public abstract class CarDecorate {

    private Car car;

    public CarDecorate(Car car){
        this.car = car;
    }

    public abstract void show();

    public void setCar(Car car) {
        this.car = car;
    }

    public Car getCar() {
        return car;
    }
}

public class FlyCarDecorate extends CarDecorate{

    public FlyCarDecorate(Car car) {
        super(car);
    }

    @Override
    public void show() {
        this.getCar().run();
        this.fly();
    }

    public void fly(){
        System.out.println("我可以飞。。。");
    }
}

public class RunCar implements Car{

    @Override
    public void show() {
        this.run();
    }

    @Override
    public void run() {
        System.out.println("能跑。。。");
    }
}

public class MainClass {
    public static void main(String[] args) {
        Car car = new RunCar();
        CarDecorate carDecorate = new FlyCarDecorate(car);
        carDecorate.show();
    }
}

装饰者模式,从字面意思上来说,就是装饰,修饰,在生活中的例子也是很多,比如女生化妆啊,这个模式我感觉最大的好处就是复用一些共同的功能。

9、建造者模式:

  创建者模式又叫建造者模式,是将一个复杂的对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。创建者模式隐藏了复杂对象的创建过程,它把复杂对象的创建过程加以抽象,通过子类继承或者重载的方式,动态的创建具有复合属性的对象。
在这里插入图片描述
在这里插入图片描述
Product(产品角色): 一个具体的产品对象。
Builder(抽象建造者): 创建一个Product对象的各个部件指定的抽象接口。
ConcreteBuilder(具体建造者): 实现抽象接口,构建和装配各个部件。
Director(指挥者): 构建一个使用Builder接口的对象。它主要是用于创建一个复杂的对象。它主要有两个作用,一是:隔离了客户与对象的生产过程,二是:负责控制产品对象的生产过程。

public class House {
    private String floor;
    private String wall;
    private String top;

    public void setFloor(String floor) {
        this.floor = floor;
    }

    public String getFloor() {
        return floor;
    }

    public void setTop(String top) {
        this.top = top;
    }

    public String getTop() {
        return top;
    }

    public void setWall(String wall) {
        this.wall = wall;
    }

    public String getWall() {
        return wall;
    }
}

public interface HouseBuilder {

    void makeFloor();

    void makeWall();

    void makeTop();

    House house();
}

public class SecondFloor implements HouseBuilder{

    House house = new House();

    @Override
    public void makeFloor() {
        house.setFloor("二层>>>house.getFloor()");
    }

    @Override
    public void makeWall() {
        house.setWall("二层>>>house.getWall()");
    }

    @Override
    public void makeTop() {
        house.setTop("二层>>>house.getTop()");
    }

    @Override
    public House house() {
        return house;
    }
}

public class ThreeFloor implements HouseBuilder{

    House house = new House();

    @Override
    public void makeFloor() {
        house.setFloor("三层>>>house.getFloor()");
    }

    @Override
    public void makeWall() {
        house.setWall("三层>>>house.getWall()");
    }

    @Override
    public void makeTop() {
        house.setTop("三层>>>house.getTop()");
    }

    @Override
    public House house() {
        return house;
    }
}

public class MainClass {
    public static void main(String[] args) {
        /*House house = new House();
        house.setFloor("11");
        house.setWall("22");
        house.setTop("33");*/


        HouseBuilder houseBuilder = new ThreeFloor();

        houseBuilder.makeFloor();
        houseBuilder.makeWall();
        houseBuilder.makeTop();
        House house = houseBuilder.house();
        System.out.println(house.getFloor());
        System.out.println(house.getTop());
        System.out.println(house.getWall());
    }
}

对于建造者模式,从字面意思上来说,就是建造,在实际的生活中体现在比如有的人结婚的时候先盖二层楼,如果女方不同意还可以结成三层楼,如果盖完三层,女方想要二层的,就把三层拆了,估计也没有这种要求哈,这边是建造者模式,对于原料我不会去修改,我只是去修改原料出来的产品。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值