精华内容
下载资源
问答
  • 分享一个大牛的人工智能教程。零基础!通俗易懂!风趣幽默!希望你也加入到人工智能的队伍中来!...也许读者知道 Java IO 中的几个是典型的装饰模式的... 所以说嘛,要找到纯的严格符合设计模式的代码还是比较难的。

    分享一个大牛的人工智能教程。零基础!通俗易懂!风趣幽默!希望你也加入到人工智能的队伍中来!请点击http://www.captainbed.net

    要把装饰模式说清楚明白,不是件容易的事情。也许读者知道 Java IO 中的几个类是典型的装饰模式的应用,但是读者不一定清楚其中的关系,也许看完就忘了,希望看完这节后,读者可以对其有更深的感悟。

    首先,我们先看一个简单的图,看这个图的时候,了解下层次结构就可以了:

    Image

    我们来说说装饰模式的出发点,从图中可以看到,接口 Component 其实已经有了 ConcreteComponentA 和 ConcreteComponentB 两个实现类了,但是,如果我们要增强这两个实现类的话,我们就可以采用装饰模式,用具体的装饰器来装饰实现类,以达到增强的目的。

    从名字来简单解释下装饰器。既然说是装饰,那么往往就是添加小功能这种,而且,我们要满足可以添加多个小功能。最简单的,代理模式就可以实现功能的增强,但是代理不容易实现多个功能的增强,当然你可以说用代理包装代理的多层包装方式,但是那样的话代码就复杂了。

    首先明白一些简单的概念,从图中我们看到,所有的具体装饰者们 ConcreteDecorator* 都可以作为 Component 来使用,因为它们都实现了 Component 中的所有接口。它们和 Component 实现类 ConcreteComponent* 的区别是,它们只是装饰者,起装饰作用,也就是即使它们看上去牛逼轰轰,但是它们都只是在具体的实现中加了层皮来装饰而已。

    注意这段话中混杂在各个名词中的 Component 和 Decorator,别搞混了。

    下面来看看一个例子,先把装饰模式弄清楚,然后再介绍下 Java IO 中的装饰模式的应用。

    最近大街上流行起来了“快乐柠檬”,我们把快乐柠檬的饮料分为三类:红茶、绿茶、咖啡。在这三大类的基础上,又增加了许多的口味,什么金桔柠檬红茶、金桔柠檬珍珠绿茶、芒果红茶、芒果绿茶、芒果珍珠红茶、烤珍珠红茶、烤珍珠芒果绿茶、椰香胚芽咖啡、焦糖可可咖啡等等。每家店都有很长的菜单,但是仔细看下,其实原料也没几样,但是可以搭配出很多组合。如果顾客需要,很多没出现在菜单中的饮料他们也是可以做的。

    在这个例子中,红茶、绿茶、咖啡是最基础的饮料,其他的像金桔、柠檬、芒果、珍珠、椰果、焦糖等都属于装饰用的。当然,在开发中,我们确实可以像门店一样,开发这些类:LemonBlackTea、LemonGreenTea、MangoBlackTea、MangoLemonGreenTea…但是,很快我们就发现,这样子干肯定是不行的,这会导致我们需要组合出所有的可能,而且如果客人需要在红茶中加双份柠檬怎么办?三份柠檬怎么办?

    不说废话了,上代码。

    首先,定义饮料抽象基类:

    public abstract class Beverage {
    
        // 返回描述
        public abstract String getDescription();
    
        // 返回价格
        public abstract double cost();
    }

    然后是三个基础饮料实现类,红茶、绿茶和咖啡:

    public class BlackTea extends Beverage {
    
        public String getDescription() {
            return "红茶";
        }
        
        public double cost() {
            return 10;
        }
    
    }
    
    public class GreenTea extends Beverage {
    
        public String getDescription() {
            return "绿茶";
        }
    
        public double cost() {
            return 11;
        }
    
    }
    
    // 咖啡省略...

    定义调料,也就是装饰者的基类,此类必须继承自 Beverage:

    // 调料
    public abstract class Condiment extends Beverage {
    }

    然后我们来定义柠檬、芒果等具体的调料,它们属于装饰者,毫无疑问,这些调料肯定都需要继承调料 Condiment 类:

    public class Lemon extends Condiment {
    
        private Beverage bevarage;
    
        // 这里很关键,需要传入具体的饮料,例如传入没有被装饰的红茶或绿茶,
        // 当然也可以传入已经装饰好的芒果绿茶,这样可以做芒果柠檬绿茶
        public Lemon(Beverage bevarage) {
            this.bevarage = bevarage;
        }
    
        public String getDescription() {
    
            // 装饰
            return bevarage.getDescription() + ",加柠檬";
        }
    
        public double cost() {
    
            // 装饰
            return beverage.cost() + 2; // 加柠檬需要 2 元
        }
    
    }
    
    public class Mango extends Condiment {
    
        private Beverage bevarage;
    
        public Mango(Beverage bevarage) {
            this.bevarage = bevarage;
        }
    
        public String getDescription() {
            return bevarage.getDescription() + ",加芒果";
        }
    
        public double cost() {
            return beverage.cost() + 3; // 加芒果需要 3 元
        }
    
    }
    
    // 给每一种调料都加一个类...

    看客户端调用:

    public static void main(String[] args) {
    
        // 首先,我们需要一个基础饮料,红茶、绿茶或咖啡
        Beverage beverage = new GreenTea();
    
        // 开始装饰
        beverage = new Lemon(beverage); // 先加一份柠檬
        beverage = new Mongo(beverage); // 再加一份芒果
    
        // "绿茶,加柠檬,加芒果 价格:¥16"
        System.out.println(beverage.getDescription() + " 价格:¥" + beverage.cost());
    }

    如果我们需要芒果-珍珠-双份柠檬-红茶:

    Beverage beverage = new Mongo(new Pearl(new Lemon(new Lemon(new BlackTea()))));

    是不是很变态?

    看看下图可能会清晰一些:

    Image

    到这里,大家应该已经清楚装饰模式了吧。

    下面,我们再来说说 Java IO 中的装饰模式。看下图 InputStream 派生出来的部分类:

    Image

    我们知道 InputStream 代表了输入流,具体的输入来源可以是文件(FileInputStream)、管道(PipedInputStream)、数组(ByteArrayInputStream)等,这些就像前面奶茶的例子中的红茶、绿茶,属于基础输入流。

    FilterInputStream 承接了装饰模式的关键节点,它的实现类是一系列装饰器,比如 BufferedInputStream 代表用缓冲来装饰,也就使得输入流具有了缓冲的功能,LineNumberInputStream 代表用行号来装饰,在操作的时候就可以取得行号了,DataInputStream 的装饰,使得我们可以从输入流转换为 Java 中的基本类型值。

    当然,在 Java IO 中,如果我们使用装饰器的话,就不太适合面向接口编程了,如:

    InputStream inputStream = new LineNumberInputStream(new BufferedInputStream(new FileInputStream("")));

    这样的结果是,inputStream 还是不具有读取行号的功能,因为读取行号的方法定义在 LineNumberInputStream 类中。

    我们应该像下面这样使用:

    DataInputStream is = new DataInputStream(
                         new BufferedInputStream(
                         new FileInputStream("")));

    所以说嘛,要找到纯的严格符合设计模式的代码还是比较难的。

    展开全文
  • 按照目的来分,设计模式可以分为创建型模式、结构型模式和行为型模式。 创建型模式用来处理对象的创建过程;结构型模式用来处理或者对象的组合;行为型模式用来对或对象怎样交互和怎样分配职责进行描述。 ...
    引用《软件秘笈-设计模式那点事》书籍:
    
    按照目的来分,设计模式可以分为创建型模式、结构型模式和行为型模式。
    创建型模式用来处理对象的创建过程;结构型模式用来处理类或者对象的组合;行为型模式用来对类或对象怎样交互和怎样分配职责进行描述。
    
    
    创建型模式用来处理对象的创建过程,主要包含以下5种设计模式:
    
     工厂方法模式(Factory Method Pattern)
     抽象工厂模式(Abstract Factory Pattern)
     建造者模式(Builder Pattern)
     原型模式(Prototype Pattern)
     单例模式(Singleton Pattern)
    
    
    结构型模式用来处理类或者对象的组合,主要包含以下7种设计模式:
    
     适配器模式(Adapter Pattern)
     桥接模式(Bridge Pattern)
     组合模式(Composite Pattern)
     装饰者模式(Decorator Pattern)
     外观模式(Facade Pattern)
     享元模式(Flyweight Pattern)
     代理模式(Proxy Pattern)
    
    
    行为型模式用来对类或对象怎样交互和怎样分配职责进行描述,主要包含以下11种设计模式:
     责任链模式(Chain of Responsibility Pattern)
     命令模式(Command Pattern)
     解释器模式(Interpreter Pattern)
     迭代器模式(Iterator Pattern)
     中介者模式(Mediator Pattern)
     备忘录模式(Memento Pattern)
     观察者模式(Observer Pattern)
     状态模式(State Pattern)
     策略模式(Strategy Pattern)
     模板方法模式(Template Method Pattern)
     访问者模式(Visitor Pattern) 

    展开全文
  • 设计模式(二)结构型模式

    千次阅读 2018-08-04 20:58:08
    总体来说设计模式分为三大: 创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。 结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模...

    Java 中一般认为有23 种设计模式,我们不需要所有的都会,但是其中常用的几种设计模式应该去掌握。
    下面列出了所有的设计模式。需要掌握的设计模式我单独列出来了,当然能掌握的越多越好。
    总体来说设计模式分为三大类:
    创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
    结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
    行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

    总结:每一种设计模式,代码去理解实现方式,根据结构图记忆理解。本文没有给出具体代码,可以在码云下载代码使用,本文适合不断翻看理解这些设计模式
    码云代码:https://gitee.com/huopusa/arithmetic.git

    六、适配器模式 adapter

    分类
    类适配器、对象适配器、接口适配器
    UML图
    这里写图片描述
    适配器模式应用场景
    类适配器与对象适配器的使用场景一致,仅仅是实现手段稍有区别,二者主要用于如下场景
    (1)想要使用一个已经存在的类,但是它却不符合现有的接口规范,导致无法直接去访问,这时创建一个适配器就能间接去访问这个类中的方法。
    (2)我们有一个类,想将其设计为可重用的类(可被多处访问),我们可以创建适配器来将这个类来适配其他没有提供合适接口的类。
    接口适配器使用场景:
    1)想要使用接口中的某个或某些方法,但是接口中有太多方法,我们要使用时必须实现接口并实现其中的所有方法,可以使用抽象类来实现接口,并不对方法进行实现(仅置空),然后我们再继承这个抽象类来通过重写想用的方法的方式来实现。这个抽象类就是适配器。
    参照博文:
    https://blog.csdn.net/yujin753/article/details/46287643
    http://www.cnblogs.com/V1haoge/p/6479118.html

    七、装饰器模式 decorator

    https://www.cnblogs.com/jzb-blog/p/6717349.html

    Component为统一接口这里写图片描述,也是装饰类和被装饰类的基本类型。
    ConcreteComponent为具体实现类,也是被装饰类,他本身是个具有一些功能的完整的类。
    Decorator是装饰类,实现了Component接口的同时还在内部维护了一个ConcreteComponent的实例,并可以通过构造函数初始化。而Decorator本身,通常采用默认实现,他的存在仅仅是一个声明:我要生产出一些用于装饰的子类了。而其子类才是赋有具体装饰效果的装饰产品类。
    ConcreteDecorator是具体的装饰产品类,每一种装饰产品都具有特定的装饰效果。可以通过构造器声明装饰哪种类型的ConcreteComponent,从而对其进行装饰。
    优点:
    装饰器模式是一种用于代替继承的技术,无需通过继承增加子类就能扩展对象的新功能。使用对象的关联关系代替继承关系,更加灵活,同时避免类型体系的快速膨胀。
    代码:

    public interface ICar {
        void move();
    }
    //ConcreteComponent 具体构件角色(真实对象)
    class Car implements ICar {
    
        @Override
        public void move() {
            System.out.println("陆地上跑!");
        }
    
    }
    class SuperCar implements ICar {
        private ICar car;
        public SuperCar(ICar car) {
            this.car = car;
        }
        @Override
        public void move() {
            car.move();
        }
    }
    //ConcreteDecorator具体装饰角色
    class FlyCar extends SuperCar {
        public FlyCar(ICar car) {
            super(car);
        }
        public void fly() {
            System.out.println("天上飞");
        }
        @Override
        public void move() {
            super.move();
            fly();
        }
    }
    //ConcreteDecorator具体装饰角色
    class WaterCar extends SuperCar {
        public WaterCar(ICar car) {
            super(car);
        }
        public void swim() {
            System.out.println("水里游");
        }
        @Override
        public void move() {
            super.move();
            swim();
        }
    }
    //ConcreteDecorator具体装饰角色
    class AICar extends SuperCar {
        public AICar(ICar car) {
            super(car);
        }
        public void autoMove() {
            System.out.println("自动跑");
        }
        @Override
        public void move() {
            super.move();
            autoMove();
        }

    测试客户端:

    public class Client {
        public static void main(String[] args) {
            ICar car = new Car();
            car.move();
    
            System.out.println("------------增加新的功能:飞行");
            ICar flycar = new FlyCar(car);
            flycar.move();
    
            System.out.println("------------增加新的功能:水里游");
            ICar waterCar = new WaterCar(car);
            waterCar.move();
    
            System.out.println("------------增加两个新的功能,飞行,水里游");
            ICar waterCar2 = new WaterCar(flycar);
            waterCar2.move();
    
            System.out.println("------------累加3个新的功能,飞行,水里游,自动驾驶");
            ICar superCar = new AICar(waterCar2);
            superCar.move();
        }
    }

    运行结果:这里写图片描述

    八、代理模式 proxy

    特点:
    1、 执行者、 被代理人
    2、 对于被代理人来说, 这件事情是一定要做的, 但是我自己又不想做或者没有时间做, 找代理。
    3、 需要获取到被代理的人个人资料。
    4、关心过程
    例子:
    租房中介: 中介和你
    火车票黄牛: 黄牛和你
    媒人: 媒婆和你
    明星经纪人: 经纪人和明星 刘德华要开演唱会(长沙) 、 准备工作和善后工作

    AOP中使用场景
    事务代理(声明式事务, 哪个方法需要加事务, 哪个方法不需要加事务)
    日志监听
    假如我们定义了一个service 方法
    开启一个事务(open) 代理来做
    事务的执行 执行我们的service方法
    监听到是否有异常, 可能需要根据异常的类型来决定这个事务是否要回滚还是继续提交 代理来做
    (commit/rollback) 代理来做
    事务要关闭(close) 代理来做

    参照
    https://blog.csdn.net/qq_33214833/article/details/70230891
    注:代理模式应用比较广泛,使代码开发更加灵活

    九、外观模式 Facade (门面模式)

    概念:
    外观模式(Facade),他隐藏了系统的复杂性,并向客户端提供了一个可以访问系统的接口。这种类型的设计模式属于结构性模式。为子系统中的一组接口提供了一个统一的访问接口,这个接口使得子系统更容易被访问或者使用。
    uml图
    这里写图片描述
     简单来说,该模式就是把一些复杂的流程封装成一个接口供给外部用户更简单的使用。这个模式中,设计到3个角色。
      1).门面角色:外观模式的核心。它被客户角色调用,它熟悉子系统的功能。内部根据客户角色的需求预定了几种功能的组合。
      2).子系统角色:实现了子系统的功能。它对客户角色和Facade时未知的。它内部可以有系统内的相互交互,也可以由供外界调用的接口。
      3).客户角色:通过调用Facede来完成要实现的功能
    注:因门面模式Spring+接口调用应用太广泛,没有写具体代码
    十、桥接模式 bridge
    https://www.cnblogs.com/lixiuyu/p/5923160.html

    1.桥接模式的优点
    (1)实现了抽象和实现部分的分离
    桥接模式分离了抽象部分和实现部分,从而极大的提供了系统的灵活性,让抽象部分和实现部分独立开来,分别定义接口,这有助于系统进行分层设计,从而产生更好的结构化系统。对于系统的高层部分,只需要知道抽象部分和实现部分的接口就可以了。
    (2)更好的可扩展性
    由于桥接模式把抽象部分和实现部分分离了,从而分别定义接口,这就使得抽象部分和实现部分可以分别独立扩展,而不会相互影响,大大的提供了系统的可扩展性。
    (3)可动态的切换实现
    由于桥接模式实现了抽象和实现的分离,所以在实现桥接模式时,就可以实现动态的选择和使用具体的实现。
    (4)实现细节对客户端透明,可以对用户隐藏实现细节。
    2.桥接模式的缺点
    (1)桥接模式的引入增加了系统的理解和设计难度,由于聚合关联关系建立在抽象层,要求开发者针对抽象进行设计和编程。
    (2)桥接模式要求正确识别出系统中两个独立变化的维度,因此其使用范围有一定的局限性。
    3.桥接模式的使用场景
    (1)如果一个系统需要在构件的抽象化角色和具体化角色之间增加更多的灵活性,避免在两个层次之间建立静态的继承联系,通过桥接模式可以使它们在抽象层建立一个关联关系。
    (2)抽象化角色和实现化角色可以以继承的方式独立扩展而互不影响,在程序运行时可以动态将一个抽象化子类的对象和一个实现化子类的对象进行组合,即系统需要对抽象化角色和实现化角色进行动态耦合。
    (3)一个类存在两个独立变化的维度,且这两个维度都需要进行扩展。
    (4)虽然在系统中使用继承是没有问题的,但是由于抽象化角色和具体化角色需要独立变化,设计要求需要独立管理这两者。
    (5)对于那些不希望使用继承或因为多层次继承导致系统类的个数急剧增加的系统,桥接模式尤为适用
    代码

    /**
     * 定义接口--被实现者
     */
    public interface Implementor {
        public void operation();
    }
    /**
     * 实现者A
     */
    public class ConcreateImplementorA implements Implementor {
        @Override
        public void operation() {
            System.out.println("这个是ConcreateImplementorA的operation方法");
        }
    }
    /**
     * 实现者B
     */
    public class ConcreateImplementorB implements Implementor {
        @Override
        public void operation() {
            System.out.println("这个是ConcreateImplementorB的operation方法");
        }
    }
    /**
     *  桥接类
     */
    public abstract class Abstraction {
        private Implementor implementor;
        public Implementor getImplementor() {
            return implementor;
        }
        public void setImplementor(Implementor implementor){
            this.implementor = implementor;
        }
        // 引用接口
        protected void operation(){
            implementor.operation();
        }
    }
    /**
     * 桥接实现类
     */
    public class RefinedAbstraction extends Abstraction {
        @Override
        protected void operation() {
            super.operation();
        }
    }
    /**
     * client 调用测试
     */
    public class BridgeTest {
        public static void main(String[] args) {
            Abstraction abstraction = new RefinedAbstraction();
    
            //调用第一个实现类
            abstraction.setImplementor(new ConcreateImplementorA());
            abstraction.operation();
    
            //调用第二个实现类
            abstraction.setImplementor(new ConcreateImplementorB());
            abstraction.operation();
        }
    }

    十一、组合模式 Composite

    1、UML结构
    这里写图片描述

    实例图这里写图片描述

    2、角色组成
    抽象构件角色(component):是组合中的对象声明接口,在适当的情况下,实现所有类共有接口的默认行为。声明一个接口用于访问和管理Component子部件。这个接口可 以用来管理所有的子对象。(可选)在递归结构中定义一个接口,用于访问一个父部件,并在合适的情况下实现它。
    树叶构件角色(Leaf):在组合树中表示叶节点对象,叶节点没有子节点。并在组合中定义图元对象的行为。
    树枝构件角色(Composite):定义有子部件的那些部件的行为。存储子部件。在Component接口中实现与子部件有关的操作。
    客户角色(Client):通过component接口操纵组合部件的对象。

    3、组合模式的优缺点
    优点:
    组合模式使得客户端代码可以一致地处理对象和对象容器,无需关系处理的单个对象,还是组合的对象容器。
    将”客户代码与复杂的对象容器结构“解耦。
    可以更容易地往组合对象中加入新的构件。
    缺点: 使得设计更加复杂。客户端需要花更多时间理清类之间的层次关系。(这个是几乎所有设计模式所面临的问题)。
    注意的问题:
    有时候系统需要遍历一个树枝结构的子构件很多次,这时候可以考虑把遍历子构件的结构存储在父构件里面作为缓存。
    客户端尽量不要直接调用树叶类中的方法(在我上面实现就是这样的,创建的是一个树枝的具体对象;),而是借用其父类(Graphics)的多态性完成调用,这样可以增加代码的复用性。
    4、组合模式的使用场景
    在以下情况下应该考虑使用组合模式:
    当想表达对象的部分-整体的层次结构时。
    希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象时。
    参考:https://www.cnblogs.com/snaildev/p/7647190.html

    十二、享元模式 Flyweight Pattern

    http://www.cnblogs.com/java-my-life/archive/2012/04/26/2468499.html
    享元模式:以共享的方式高效的支持大量的细粒度对象。通过复用内存中已存在的对象,降低系统创建对象实例的性能消耗。
    java的 String 类型就是享元模式
    这里写图片描述
    单纯享元模式所涉及到的角色如下:
      ●  抽象享元(Flyweight)角色 :给出一个抽象接口,以规定出所有具体享元角色需要实现的方法。
      ●  具体享元(ConcreteFlyweight)角色:实现抽象享元角色所规定出的接口。如果有内蕴状态的话,必须负责为内蕴状态提供存储空间。
      ●  享元工厂(FlyweightFactory)角色 :本角色负责创建和管理享元角色。本角色必须保证享元对象可以被系统适当地共享。当一个客户端对象调用一个享元对象的时候,享元工厂角色会检查系统中是否已经有一个符合要求的享元对象。如果已经有了,享元工厂角色就应当提供这个已有的享元对象;如果系统中没有一个适当的享元对象的话,享元工厂角色就应当创建一个合适的享元对象。
    复合享元角色所涉及到的角色如下:
      ●  抽象享元(Flyweight)角色 :给出一个抽象接口,以规定出所有具体享元角色需要实现的方法。
      ●  具体享元(ConcreteFlyweight)角色:实现抽象享元角色所规定出的接口。如果有内蕴状态的话,必须负责为内蕴状态提供存储空间。
      ●  复合享元(ConcreteCompositeFlyweight)角色 :复合享元角色所代表的对象是不可以共享的,但是一个复合享元对象可以分解成为多个本身是单纯享元对象的组合。复合享元角色又称作不可共享的享元对象。
      ●  享元工厂(FlyweightFactory)角色 :本角 色负责创建和管理享元角色。本角色必须保证享元对象可以被系统适当地共享。当一个客户端对象调用一个享元对象的时候,享元工厂角色会检查系统中是否已经有 一个符合要求的享元对象。如果已经有了,享元工厂角色就应当提供这个已有的享元对象;如果系统中没有一个适当的享元对象的话,享元工厂角色就应当创建一个 合适的享元对象。
    享元模式的优缺点
      享元模式的优点在于它大幅度地降低内存中对象的数量。但是,它做到这一点所付出的代价也是很高的:
      ●  享元模式使得系统更加复杂。为了使对象可以共享,需要将一些状态外部化,这使得程序的逻辑复杂化。
      ●  享元模式将享元对象的状态外部化,而读取外部状态使得运行时间稍微变长。

    享元模式实例
    其实在Java中就存在这种类型的实例:String。
    Java中将String类定义为final(不可改变的),JVM中字符串一般保存在字符串常量池中,这个字符串常量池在jdk 6.0以前是位于常量池中,位于永久代,而在JDK 7.0中,JVM将其从永久代拿出来放置于堆中。
      我们使用如下代码定义的两个字符串指向的其实是同一个字符串常量池中的字符串值。

    String s1 = "abc";
    String s2 = "abc";

    如果我们以s1==s2进行比较的话所得结果为:true,因为s1和s2保存的是字符串常量池中的同一个字符串地址。这就类似于我们今天所讲述的享元模式,字符串一旦定义之后就可以被共享使用,因为他们是不可改变的,同时被多处调用也不会存在任何隐患。
    享元模式使用的场景:
        当我们项目中创建很多对象,而且这些对象存在许多相同模块,这时,我们可以将这些相同的模块提取出来采用享元模式生成单一对象,再使用这个对象与之前的诸多对象进行配合使用,这样无疑会节省很多空间。

    参照例子(更加形象的例子):https://www.cnblogs.com/V1haoge/p/6542449.html

    展开全文
  • 设计模式结构型模式

    千次阅读 2011-11-05 00:32:20
    下面说一下结构型模式:结构型模式是描述如何将对象结合在一起,形成一个...在GoF设计模式中,结构型模式有:  1.适配器模式 Adapter  2.桥接模式 Bridge  3.组合模式 Composite  4.装饰模式 Decorator  5

           下面说一下结构型模式:结构型模式是描述如何将类对象结合在一起,形成一个更大的结构,结构模式描述两种不同的东西:类与类的实例。故可以分为类结构模式和对象结构模式。

    在GoF设计模式中,结构型模式有:

          1.适配器模式 Adapter

          2.桥接模式 Bridge

          3.组合模式 Composite

          4.装饰模式 Decorator

          5.外观模式 Facade

          6.享元模式 Flyweight

          7.代理模式 Proxy  

    具体来说:

    适配器模式Adapter

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

          两个成熟的类需要通信,但是接口不同,由于开闭原则,我们不能去修改这两个类的接口,所以就需要一个适配器来完成衔接过程。

          变压器就是很好的适配器模式的例子。用电设备所需要的电压是9V,但是电线上的电压却是220V的,我们不能去更改它们的电压输入或输出,所以我们用到了变压器。变压器是220V的输入,9V的输出。这样就可以将200V的电压变为9V的电压,用变压器将用电设备连接到了电线上工作了。

           上面两幅图中,都是Client端需要Request这个方法,但是Adaptee没有这个方法,所以就需要提供一个中间件/包装类(Wrapper)Adapter类来衔接。不同的是第一幅图Adapter继承自Adaptee,而第二幅图是在Adapter类中包装了一个Adaptee的实例。这就决定了第一幅图讲的是“类的结构模式”,而第二幅图则是“对象的结构模式”。

    桥接模式 Bridge

          桥接模式将抽象部分与它的实现部分分离,是它们都可以独立地变化。它很好的支持了开闭原则和组合锯和复用原则。实现系统可能有多角度分类,每一种分类都有可能变化,那么就把这些多角度分离出来让他们独立变化,减少他们之间的耦合。

          2个相互耦合的系列,每个系列都有各自的产品变动。将这2个系列抽象成2个角色类,将各自的变化封装到对象的角色类中,然后再将2个角色类之间用组合的关系表示,这样就大大简化了使用类继承的复杂性,逻辑变得清晰了,易于扩展和维护。

          桥接模式封装了变化,完成了解耦,实现了弱耦合

    组合模式 Composite

          组合模式将对象组合成树形结构以表示部分-整体的层次结构,组合模式使得用户对单个对象和组合对象的使用具有一致性。就像“放羊娃的故事”一样(放羊—赚钱—娶妻---生娃—放羊…)。

          廊坊师范学院=14个二级学院+院长、副院长;每一个二级学院=多个专业+二级学院院长、副院长;每一个专业有学生+班委。大学院可以增删二级学院和副院长,二级学院的结构跟大学院几乎一样,所以也可以增删专业和副院长。虽然结构复杂,但是操作简单,只需要进行简单的递归调用即可。

    装饰模式 Decorator

           装饰模式动态地给一个对象添加一些额外的职责,就增加功能来说,它比生成子类更灵活。也可以这样说,装饰模式把复杂类中的核心职责和装饰功能区分开了,这样既简化了复杂类,有去除了相关类中重复的装饰逻辑。装饰模式没有通过继承原有类来扩展功能,但却达到了一样的目的,而且比继承更加灵活,所以可以说装饰模式是继承关系的一种替代方案。

           孙悟空有72变,每一变都可以给他带来一个附加功能,变成鱼可以在水下呼吸,变成鸟可以在天上飞翔。这就是典型的装饰模式。

           装饰模式解耦了核心和装饰功能,锁业也是强调了松耦合 

    外观模式 Facade

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

           外观模式中,客户对各个具体的子系统是不了解的,所以对这些子系统进行了封装,对外只提供了用户所明白的单一而简单的接口,用户直接使用这个接口就可以完成操作,而不用去理睬具体的过程,而且子系统的变化不会影响到用户,这样就做到了信息隐蔽。

           这就相当于新生接待员。新生对入学流程不清楚,但是接待员学长可是明白的。学生跟着接待员就可以把各个手续办理完毕了。

     

    享元模式 Flyweight

          享元模式为运用共享技术有效的支持大量细粒度的对象。因为它可以通过共享大幅度地减少单个实例的数目,避免了大量非常相似类的开销。.

          享元模式是一个类别的多个对象共享这个类别的一个对象,而不是各自再实例化各自的对象。这样就达到了节省内存的目的。 

     代理模式 Proxy

          为其他对象提供一种代理,并由代理对象控制对原对象的引用,以间接控制对原对象的访问。

    我们想上外国的网站,但是国家给限制了,所以我们就需要一个可以登录到外国网站的ip,通过连接到这个ip,再通过这个ip去访问外国网站。

     

    代理模式与外观模式的区别

    代理的客户对象无法直接访问目标对象,代理对象提供对单独目标对象的访问控制,而外观模式的客户对象可以直接访问子系统中的各个对象,但通常由外观对象提供对子系统个元件功能的简化的共同层次的调用接口。

     

    代理模式与适配器的区别

             二者都属于一种衔接性质的功能。代理对象和被代理对象的接口是同一个,但是客户没法直接访问被代理者,只能通过代理对象去完成被代理对象的访问。而适配器模式是将多个子系统封装起来,提供一个统一的外部接口,客户只需要使用这个外部接口即可访问对象的子系统了。

            

    外观跟适配器的区别

             二者都是对显存系统的封装。外观模式定义了一个新的接口,而适配器则是复用了一个原有的接口;适配器是用来适配对象的,而外观则是用来适配整个子系统的。

     

    展开全文
  • 设计模式之装饰模式(结构型)

    千次阅读 2019-03-02 23:37:30
    装饰模式:装饰模式就是允许向一个现有的对象添加新的功能,同时又不改变其结构,装饰模式是一种对象结构型设计模式。 二、模式角色 对于装饰模式可以分为如下角色 Component:抽象构件 ConcreteComponent:具体...
  • 设计模式可以分为创建型、结构型和行为型。 创建型 对的现实化进行了抽象,能够使软件模块做到与对象的创建和组织无关。 功能:的创建 创建型: 单例模式、抽象工厂模式、建造者模式、工厂模式、原型模式 结构型 ...
  • 设计模式之适配器模式(结构型)

    千次阅读 2019-03-11 23:06:00
    文章目录模式定义模式角色模式分析模式例子模式...适配器模式既可以作为类结构型模式,也可以作为对象结构型模式模式角色 适配器模式包括如下角色 Traget(目标抽象) Adapter(适配器) Adaptee(适配者...
  • 设计模式总结之结构型模式

    千次阅读 热门讨论 2014-05-24 17:28:39
    在设计模式中,结构设计模式分为
  • 结构型模式分类与简介

    千次阅读 2019-03-06 09:31:11
    在GoF设计模式中,结构型模式有: 1.适配器模式 Adapter 适配器模式是将一个的接口转换成客户希望的另外一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些可以一起工作。 ...
  • 设计模式-结构型软件设计模式(二)

    千次阅读 2017-07-13 20:07:02
    适配器模式分为两种,一种是适配器,一种是对象适配器模式。 (1)适配器 (2)对象适配器 示例现在有一个student,现在要在要添加一个功能read(); 适配器class student { public St
  • 这种类型的设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结构的方式。享元模式尝试重用现有的同类对象,如果未找到匹配的对象,则创建新对象。我们将通过创建 5 个对象来画出 20 个分布于...
  • 这种类型的设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结构的方式。运用了共享技术有效的支持大量细粒度对象的重复利用,时较为轻量级的对象结构型模式。享元模式的产生背景例如,围棋和...
  • 博主在大三的时候有上过...总体来说设计模式分为三大:创建型模式、结构型模式和行为型模式。博主的上一篇文章已经提到过创建型模式,此外该文章还有设计模式概况和设计模式的六大原则。设计模式的六大原则是设计模式
  • 设计模式代码下载地址 设计模式代码下载地址 1 适配器模式 在设计模式中,适配器模式(英语:adapter pattern)有时候也称包装样式或者包装(wrapper)。将一个的接口转接成用户所期待的。一个适配使得因...
  • javascript设计模式之装饰器模式 js的设计模式分为创建型模式,结构型模式和行为模式结构模式描述了 如何组合对象以提供新的功能。装饰器模式是一种常见的结构型模式,我们可以以一个基础对象为基础,来给它加上若干...
  • 结构模式用来描述的是如何组合类 的对象一获得更大的结构分为类描述和对象描述。类描述的是如何通过继承提供更有用的接口而对象接口描述的是通过使用对象的组合或将对象含在其他对象里面一伙的更有用的结构》 ...
  • 【设计模式】设计模式之结构型模式(适配器、桥接、组合、装饰、外观、享元、代理)1、设计模式1.1 设计模式介绍1.2 分类2、结构型模式2.1 概述2.2 七大结构型设计模式2.2.1 适配器模式 1、设计模式 1.1 设计模式...
  • 设计模式之享元模式(结构型)

    千次阅读 2019-01-05 23:34:49
    按照Gof模式分类,享元模式属于对象结构型模式模式解释 可以共享的内容称为内部状态(Intrinsic State),需要外部环境设置的不能共享的内容称为外部状态(Extrinsic State)。享元模式需要创建一个享元工...
  • 设计模式-结构型软件设计模式(三)

    千次阅读 2017-07-14 12:37:45
    外观模式简介外观模式用来隐藏一个软件系统的所有内部细节,只提供给客户一个外观,或者叫做接口。客户直接调用该外观的方法即可,而不必担心这些方法对其他的调用的内部细节。外观模式角色(1)外观...
  • 设计模式可以分为创建型、结构型、和行为型模式。 创建型模式对的实现化过程进行了抽象,能够使软件模块做到与对象的创建和组织无关。 结构型模式描述和对象之间如何进行有效的...行为型设计模式描述和对...
  • 博主在大三的时候有上过...总体来说设计模式分为三大:创建型模式、结构型模式和行为型模式。博主的上一篇文章已经提到过创建型模式,此外该文章还有设计模式概况和设计模式的六大原则。设计模式的六大原则是设计模式
  • 代理模式是常用的结构型设计模式之一,当无法直接访问某个对象或访问某个对象存在困难时可以通过一个代理对象来间接访问,为了保证客户端使用的透明性,所访问的真实对象与代理对象需要实现相同的接口。根据代理模式...
  • 设计模式结构型-适配器模式

    千次阅读 多人点赞 2021-03-09 12:40:38
    目录第一章 适配器模式介绍第二章 适配器模式实现(适配器)2.1、关系依赖图2.2、创建交流电2.3、定义直流电2.4、创建充电器2.5、创建手机2.6、测试充电器2.7、点评该模式第三章 适配器模式实现(对象适配器)...
  • 代理模式(英语:Proxy Pattern)是程序设计中的一种设计模式。 所谓的代理者是指一个可以作为其它东西的接口。代理者可以作任何东西的接口:网络连接、内存中的大对象、文件或其它昂贵或无法复制的资源。----...
  • 结构型模式简介

    千次阅读 2015-10-15 16:04:28
    根据这一点,结构型模式可以分为类结构型模式和对象结构型模式。类结构型模式关心类的组合,由多个类可以组合成一个更大的系统,在类结构型模式中一般只存在继承关系和实现关系;而对象结构型模式
  • 接下来我们看看结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。其中适配器模式主要分为的适配器模式、对象的适配器模式、接口的适配器模式。其中的对象的...
  • 享元模式(英语:Flyweight Pattern)是一种软件设计模式。它使用共享物件,用来尽可能减少内存使用量以及分享资讯给尽可能多的相似物件;它适合用于当大量物件只是重复因而导致无法令人接受的使用大量内存。通常...
  • 我们接着讨论设计模式,上篇文章我讲完了5种创建型模式,这章开始,我将讲下7种结构型模式:适配器模式、装饰模式、代理模式、外观模式、桥接模式、组合模式、享元模式。其中对象的适配器模式是各种模式的起源,我们...
  • 设计模式--结构型模式比较

    千次阅读 2012-08-22 21:21:27
    结构型模式为了组合和对象以获得更大的结构而产生的一种指导性方法。(A structural design pattern serves as a blueprint for how different classes and objects are combined to form larger structures.)与...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 152,109
精华内容 60,843
关键字:

结构型设计模式分为类