19、设计模式

1、观察者模式(Observer Pattern):

定义对象间的一种一对多的依赖关系,当一个对象的状态发生变化时,所有依赖它的对象都得到通知并被自动更新。

Defined a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.

模式结构:

主题(Subject):主题是一个接口,该接口规定了具体主题需要实现的方法,比如,添加、删除观察者以及通知观察者更新数据的方法。

观察者(Observer):观察者是一个接口,该接口规定了具体观察者用来更新数据的方法。

具体主题(ConcreteSubject):具体主题是实现主题接口类的一个实例,该实例包含有可以经常发生变化的数据。具体主题需使用一个集合,比如ArrayList,存放观察者的引用,以便数据变化时通知具体观察者。

具体观察者(ConcreteObserver):具体观察者是实现观察者接口类的一个实例。具体观察者包含有可以存放具体主题引用的主题接口变量,以便具体观察者让具体主题将自己的引用添加到具体主题的集合中,使自己成为它的观察者,或让这个具体主题将自己从具体主题的集合中删除,使自己不再是它的观察者。

观察者UML类图:

观察者模式优点:

(1) 具体主题和具体观察者是松耦合关系。由于主题(Subject)接口仅仅依赖于观察者(Observer)接口,因此,具体主题只是知道它的观察者是实现观察者(Observer)接口的某个实例,但不需要知道具体是哪个类。

(2) 观察者模式满足”开—闭原则“。主题(Subject)接口仅仅依赖于观察者(Observer)接口,这样,就可以让创建具体主题的类也仅仅是依赖于观察者(Observer)接口,因此如果增加新的实现观察者(Observer)接口的类,不必修改创建具体主题的类的代码。

观察者模式应用情景:

(1) 当一个对象的数据更新时需要通知其他对象,但这个对象又不希望和被通知的那些对象形成紧耦合。

(2) 当一个对象的数据更新时,这个对象需要让其他对象也各自更新自己的数据,但这个对象不知道具体有多少对象需要更新数据。

Java API中Observable类与Observer接口:


2、装饰者模式(Decorator Pattern):

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

Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.

注意:装饰者模式是动态地扩展一个对象的功能,而不需要改变原始类代码的一种成熟模式。装饰模式中“具体组件”和“装饰”都是“抽象组件”的子类。由于“装饰”是“抽象组件”的子类,因此也可以把“装饰者”作为一个“被装饰者”,这意味着可以使用具体装饰类来“装饰”具体装饰类的实例。

模式结构:

抽象组件(Component):抽象组件是一个抽象类。抽象组件定义了“被装饰者”需要进行“装饰”的方法。

具体组件(ConcreteComponent):具体组件是抽象组件的一个子类,具体组件的实例称作“被装饰者”。

装饰(Decorator):装饰也是抽象组件的一个子类,但装饰还包含一个抽象组件声明的变量以保存“被装饰者”的引用。装饰可以是抽象类也可以是一个非抽象类,如果是非抽象类,那么该类的实例称作“装饰者”。

具体装饰(ConcreteDecorator):具体装饰是装饰的一个非抽象子类,具体装饰的实例称作“装饰者”。

装饰模式UML类图:

装饰模式优点:

(1) 被装饰者和装饰者是松耦合关系。由于装饰(Decorator)仅仅依赖于抽象组件(Component),因此具体装饰只知道它要装饰的对象是抽象组件某一个子类的实例,但不需知道是哪一个具体子类。

(2) 装饰模式满足“开-闭原则”。不必修改具体组件,就可以增加新的针对该具体组件的具体装饰。

(3) 可以使用多个具体装饰来装饰具体组件的实例。

装饰模式应用情景:

(1) 程序希望动态地增强类的某个对象的功能,而又不影响到该类的其他对象。

(2) 采用继承来增强对象功能不利于系统的扩展和维护。

Java IO 与装饰模式:


3、工厂模式(Factory Method):

定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method使一个类的实例化延迟到其子类。

Defined an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.

注意:工厂模式的关键是在一个接口或抽象类中定义一个抽象方法,该方法返回某个类的子类的实例,该抽象类或接口让其子类或实现该接口的类通过重写这个抽象方法返回某个子类的实例。

模式结构:

抽象产品(Product):抽象类或接口,负责定义具体产品必须实现的方法。

具体产品(ConcreteProduct):具体产品是一个类,如果Product是一个抽象类,那么具体产品是Product的子类;如果Product是一个接口,那么具体产品的实现Product接口的类。

构造者(Creator):一个接口或抽象类。构造者负责定义一个称作工厂方法的抽象方法,该方法返回具体产品类的实例。

具体构造者(ConcreteCreator):如果构造者是抽象类,具体构造者是构造者了子类;如果构造者是接口,具体构造者是实现构造者的类。具体构造者重写工厂方法使该方法返回具体产品的实例。

工厂模式UML类图:

工厂模式优点:

(1) 使用工厂方法可以让用户的代码和某个特定类的子类的代码解耦。

(2) 工厂方法使用用户不必知道它所使用的对象是怎样被创建的,只需知道该对象有哪些方法即可。

工厂模式应用情景:

(1) 用户需要一个类的子类的实例,但不希望与该类的子类形成耦合。

(2) 用户需要一个类的子类的实例,但用户不知道到该类有哪些子类可用。

Java集合框架与工厂模式:


4、抽象工厂模式(Abstract Factory Pattern):

提供一个创建一系列或相互依赖对象的接口,而无须指定它们具体的类。

Provide an interface for creating families of related or dependent objects without specifying their concrete classes.

注意:抽象工厂模式的关键是在一个抽象类或接口中定义若干个抽象方法,这些抽象方法分别返回某个类的实例,该抽象类或接口让其子类或实现该接口的类重写这些抽象方法为用户提供一系列相关的对象。

模式结构:

抽象产品(Product):一个抽象类或接口,负责定义具体产品必须实现的方法。

具体产品(ConcreteProduct):具体产品是一个类,如果Product是一个抽象类,那么具体产品是Product的子类;如果Product是一个接口,那么具体产品是实现Product接口的类。

抽象工厂(AbstractFactory):一个接口或抽象类,负责定义若干个抽象方法。

具体工厂(ConcreteFactory):如果抽象工厂是抽象类,具体工厂是抽象工厂的子类;如果抽象工厂是接口,具体工厂是实现抽象工厂的类。具体工厂重写抽象工厂中的抽象方法,使该方法返回具体产品的实例。

抽象工厂模式UML类图:


抽象工厂模式优点

(1) 抽象工厂模式可以为用户创建一系列相关的对象,使用户和创建这些对象的类脱耦。

(2) 使用抽象工厂模式可以方便的为用户配置一系列对象。用户使用不同的具体工厂就能得到一组相关的对象,同时也能避免用户混用不同系列中的对象。

(3) 在抽象工厂模式中,可以随时增加“具体工厂”为用户提供一组相关的对象。

抽象工厂模式情景:

(1) 系统需要为用户提供多个对象,但不希望用户直接使用new运算符实例化这些对象,即希望用户和创建对象的类脱耦。

(2) 系统需要为用户提供多个相关的对象,以便用户联合使用它们,但又不希望用户来决定这些对象是如何关联的。

(3) 系统需要为用户提供一系列对象,但只需用户知道这些对象有哪些方法可用,不需用户知道这些对象的创建过程。


5、单件模式(Prototype Pattern):

保证一个类仅有一个实例,并提供一个访问它的全局访问点。

Ensure a class only has one instance, and provide a global point of access to it.

注意:单件模式是关于怎样设计一个类,并使该类只有一个实例的成熟模式,该模式的关键是将类的构造方法设置为private权限,并提供一个返回它的唯一实例的类方法(static方法)。单件类的唯一实例由单件类本身控制,所以可以很好地控制用户何时访问它。

单件模式UML类图:

单件类的设计方法:

(1) 在JVM加载单件类时创建它的唯一实例。

(2) 在单件类提供的类方法中创建这个唯一实例。


6、命令模式(Command Pattern):

将一个请求封装为一个对象,从而使用户可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。

Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations.

模式结构:

接收者(Receiver):接收者是一个类的实例,该实例负责执行与请求相关的操作。

命令(Command):命令是一个接口,规定了用来封装“请求”的若干个方法,比如,execute()、undo()等方法。

具体命令(ConcreteCommand):具体命令是实现命令接口的类的实例。具体命令必须实现命令接口中的方法,比如execute()方法,使该方法封装一个“请求”。

请求者(Invoker):请求者是一个包含Command接口变量的类的实例。请求者中的Command接口的变量可以存放任何具体命令的引用。请求者负责调用具体命令,让具体命令执行那些封装了“请求”的方法,比如execute()方法。

命令模式UML类图:

命令模式优点:

(1) 在命令模式中,请求者(Invoker)不直接与接收者(Receiver)交互,即请求者(Invoker)不包含接收者(Receiver)的引用,因此彻底消除了彼此之间的耦合。

(2) 命令模式满足“开-闭原则”。如果增加新的具体命令和该命令的接收者,不必修改调用者的代码,调用者就可以使用新的命令对象;反之,如果增加新的调用者,不必修改现有的具体命令的接收者,新增加的调用者就可以使用已有的具体命令。

(3) 由于请求者的请求被封装到了具体命令中,那么就可以将具体命令保存到持久化的媒介中,在需要的时候,重新执行这个具体命令。因此,使用命令模式可以记录日志。

(4) 使用命令模式可以对请求者的“请求”进行排队。每个请求都各自对应一个具体命令,因此,可以按一定顺序执行这些具体命令。

命令模式应用情景:

(1) 程序需要在不同的时刻指定、排列和执行请求。

(2) 程序需要提供撤销操作。

(3) 程序需要支持宏操作。

Java AWT事件与命令模式:


7、适配器模式(Adapter Pattern):

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

Convert the interface of a class into another interface clients expect. Adapter lets classes work together that couldn't otherwise because of incompatible interfaces.

注意:适配器模式是将一个类的接口(被适配者)转换成客户希望的另外一个接口(目标)的成熟模式,该模式中涉及有目标、被适配者和适配器。适配器模式的关键是建立一个适配器,这个适配器实现了目标接口并包含有被适配者的引用。

模式结构:

(1) 目标(Target):目标是一个接口,该接口是客户想使用的接口。

(2) 被适配者(Adaptee):被适配者是一个已经存地的接口或抽象类,这个接口或抽象类需要适配。

(3) 适配器(Adapter):适配器是一个类,该类实现了目标接口并包含有被适配者的引用,即适配器的职责是对被适配者接口(抽象类)与目标接口进行适配。

适配器模式UML类图:

双向适配器:

package doubleAdapter;

public class TreeAndTwoElectricAdapter implements TreeElectricOutlet, TwoElectricOutlet {

	private TwoElectricOutlet twoElectricOutlet;
	private TreeElectricOutlet treeElectricOutlet;
	
	public TreeAndTwoElectricAdapter(TwoElectricOutlet twoElectricOutlet, TreeElectricOutlet treeElectricOutlet) {
		// TODO Auto-generated constructor stub
		this.twoElectricOutlet = twoElectricOutlet;
		this.treeElectricOutlet = treeElectricOutlet;
	}
	
	public TreeAndTwoElectricAdapter(TreeElectricOutlet treeElectricOutlet, TwoElectricOutlet twoElectricOutlet) {
		// TODO Auto-generated constructor stub
		this.twoElectricOutlet = twoElectricOutlet;
		this.treeElectricOutlet = treeElectricOutlet;
	}
	
	public void connectElectricCurrent() {
		if (this instanceof TreeElectricOutlet) {
			twoElectricOutlet.connectElectricCurrent();
		}
		if (this instanceof TwoElectricOutlet) {
			treeElectricOutlet.connectElectricCurrent();
		}
	}
}
Iterator接口与Enumeration接口:



8、外观模式(Facade Pattern):

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

Provide a unified interface to a set of interfaces in a subsystem. Facade defines a higher-level interface that makes the subsystem easier to use.

注意:外观模式是简化用户和子系统进行交互的成熟模式,外观模式的关键是为子系统提供一个称作外观的类,该外观的实例负责和子系统中类的实例打交道。当用户想要和子系统中的若干个类的实例打交道时,可以代替地和子系统的外观类的实例打交道。

模式结构:

子系统(Subsystem):子系统是若干个类的集合,这些类的实例协同合作为用户提供所需要的功能,子系统中任何类都不包含外观类的实例引用。

外观(Facade):外观是一个类,该类包含子系统中全部或部分类的实例引用,当用户想要和子系统中的若干个类的实例打交道时,可以代替地和子系统的外观类的实例打交道。

外观模式UML类图:

外观模式优点:

(1) 使客户和子系统中的类无耦合,并且使子系统使用起来更加方便。

(2) 外观只是提供了一个更加简洁的界面,并不影响用户直接使用子系统中的类。

(3) 子系统中任何类对其方法的内容进行修改,不影响外观类的代码。

外观模式应用情景:

(1) 对于一个复杂的子系统,需要为用户提供一个简单的交互操作。

(2) 不希望客户代码和子系统中的类有耦合,以便提高子系统的独立性和可移植性。

(3) 当整个系统需要构建一个层次结构的子系统,不希望这些子系统相互直接的交互。


9、模板方法模式(Template Method Pattern):

定义一个操作中算法的骨架,而将一些步骤延迟到子类中。模板方法使子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

Define the skeleton of an algorithm in an operation, deferring some steps to subclasses. Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm's structure.

注意:模板方法是关于怎样将若干个方法集成到一个方法中,以便形成一个解决问题的算法骨架,即将若干个方法集成到一个方法中,并称该方法为一个模板方法,或简称为模板。模板方法所调用的其他方法通常为抽象方法,这些抽象方法相当于算法骨架中的各个步骤,这些步骤的实现可以由子类去完成。

模式结构:

抽象模板(Abstract Template):抽象模板是一个抽象类。抽象模板定义了若干个方法以表示一个算法的各个步骤,这些方法中有抽象方法也有非抽象方法,其中抽象方法称作原语操作(Primitive Operation)。抽象模板中还定义了一个称作模板方法的方法,该方法不仅包含有抽象模板中表示算法步骤的方法调用,而且也可以包含有定义在抽象模板中的其他对象的方法调用,即模板方法定义了算法的骨架。

具体模板(Concrete Template):具体模板是抽象模板的子类,实现抽象模板中的原语操作。

模板方法模式UML类图:

钩子方法:

钩子方法是抽象模板中定义的具体方法,但给出了空实现或默认的实现,并允许子类重写这个具体方法。如果抽象模板不希望其中的具体方法是钩子方法,就需要将该具体方法用final修饰,要求子类必须继承该具体方法,不能重写。

某些钩子方法的作用是对模板方法中的某些步骤进行“挂钩”,即允许具体模板对算法的不同点进行“挂钩”,以确定在什么条件下执行模板方法中的哪些算法步骤。这样的钩子方法的类型都是boolean类型,其默认实现往往是返回值为true。另外一类钩子方法不是用来挂钩的,对于void类型的钩子方法,其默认实现一般为空,具体模板可以根据需要直接继承这样的钩子方法或重写这样的钩子方法。

模板方法模式优点:

(1) 可以通过在抽象模板定义模板方法给出成熟的算法步骤,同时又不限制步骤的细节,具体模板实现算法细节不会改变整个算法骨架。

(2) 在抽象模板模式中,可通过钩子方法对某些步骤进行挂钩,具体模板通过钩子可以选择算法骨架中的算法步骤。

模板方法应用情景:

(1) 设计者需要给出一个算法的固定步骤,并将某些步骤的具体实现留给子类来实现。

(2) 需要对代码进行重构,将各个子类公共行为提取出来集中到一个共同的父类中以避免代码重复。


10、迭代器模式(Iterator Pattern):

提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部表示。

Provide a way to access the elements of an aggregate object sequentially without exposing its underlying representation.

注意:迭代器模式是遍历集合的成熟模式,迭代器模式的关键是将遍历集合的任务交给一个称作迭代器的对象。

模式结构:

集合(Aggregate):一个接口,规定了具体集合需实现的操作。

具体集合(ConcreteAggregate):具体集合是实现集合接口的类的实例,具体集合按照一定的结构存储对象。具体集合应当有一个方法,该方法返回一个针对集合的具体迭代器。

迭代器(Iterator):一个接口,规定了遍历具体集合的方法,比如next()方法。

具体迭代器(ConcreteIterator):实现迭代器接口的类的实例。具体迭代器在实现迭代器接口所规定的遍历集合的方法时,比如next()方法,要保证next()方法的首次调用将按照集合的数据结构找到该集合中的一个对象,而且每当找到集合中的一个对象,立即根据该集合的存储结构得到待遍历的后继对象的引用,并保证依次调用next()方法可以遍历集合。

迭代器模式UML类图:


11、组合模式(Composite Pattern):

将对象组合成树形结构以表示"部分-整体"的层次结构。Composite使用户对单个对象和组合对象的使用具有一致性。

Composite objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly.

注意:组合模式是关于怎样将对象形成树形结构来表现整体和部分的层次结构的成熟模式。使用组合模式,可以让用户以一致的方式处理个体对象和组合对象,组合模式的关键在于无论是个体对象还是组合对象都实现了相同的接口或都是同一个抽象类的子类。

模式结构:

抽象组件(Component):是一个接口(抽象类),该接口(抽象类)定义了个体对象和组合对象需要实现的关于操作其子节点的方法,比如add()、remove()以及getChild()等方法。抽象组件也可以定义个体对象和组合对象用于操作其自身的方法,比如isLeaf()方法等。

Composite节点(Node):实现Component接口类的实例,Composite节点不仅实现Component接口,而且可以含有其他Composite节点或Leaf节点的引用。

Leaf节点(Leaf Node):实现Component接口类的实例,Leaf节点实现Component接口,不可以含有其他Composite节点或Leaf节点的引用,因此,叶节点在实现Component接口有关操作子节点的方法时,比如add()、remove()和getChild()方法,可让方法抛出一个异常,也可以实现为空操作。

组合模式UML类图:

组合模式优点:

(1) 组合械中包含个体对象和组合对象,并形成树形结构,使用户可以方便地处理个体对象和组合对象。

(2) 组到对象和个体对象实现了相同的接口,用户一般无须区分个体对象和组合对象。

(3) 当增加新的Composite节点和Leaf节点时,用户的重要代码不需要作出修改。

组合模式应用情景:

(1) 当想表示对象的部分-整体层次结构。

(2) 希望用户用一致的方式处理个体对象和组合对象。


12、状态模式(State Pattern):

允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。

Allow an object to alter its behavior when its internal state changes. The object will appear to change its class.

注意:状态模式的关键是将对象的状态封装成为独立的类,对象调用方法时,可以委托当前对象所具有的状态调用相应的方法,使当前对象看起来好像修改了它的类。

模式结构:

环境(Context):环境是一个类,该类含有抽象状态(State)声明的变量,可以引用任何具体状态的实例。用户对该环境类的实例在某种状态下的行为感兴趣。

抽象状态(State):抽象状态是一个接口或抽象类。抽象状态中定义了与环境的一个特定状态相关的若干个办法。

具体状态(ConcreteState):具体状态是实现抽象状态的类。

状态模式UML类图:

状态切换:

环境(Context)实例在某种状态下执行一个方法后,可能导致该实例的状态发生变化。程序通过使用状态模式可方便地将环境实例从一个状态切换为另一个状态。当一个环境实例有确定的若干个状态时,可以由环境实例本身负责状态的切换,该环境实例可以含有所有状态的引用,并提供设置改变状态的方法,比如

setState(State state)方法。

共享状态:

在状态模式中,要使环境的多个实例共享一个或多个状态,需要将这些状态声明为环境的静态成员,另外,一定要保证共享的状态没有自己的实例变量,否则是无法共享的。

状态模式优点:

(1) 使用一个类封装对象的一种状态,很容易增加新的状态。

(2) 在状态模式中,环境中不必出现大量的条件判断语句。环境实例所呈现的状态变得更加清晰、容易理解。

(3) 使用状态模式可以让用户程序很方便地切换环境实例的状态。

(4) 使用状态模式不会让环境的实例中出现内部状态不一致的情况。

(5) 当状态对象没有实例变量时,环境的各个实例可以共享一个状态对象。

状态模式应用情景:

(1) 一个对象的行为依赖于它的状态,并且它必须在运行时根据状态改变它的行为。

(2) 需要编写大量的条件分支语句来决定一个操作的行为,而且这些条件恰好表示对象的一种状态。


13、代理模式(Proxy Pattern):

为其它对象提供一种代理以控制对这个对象的访问。

Provide a surrogate or placeholder for another object to control access to it.

模式结构:

抽象主题(Subject):抽象主题是一个接口,该接口是对象和它的代理所共用的接口。

实际主题(RealSubject):实际主题是实现抽象主题接口的类。实际主题的实例是代理角色实例所要代理的对象。

代理(Proxy):代理是实现抽象主题接口的类(代理和实际主题实现了相同的接口)。代理含有主题接口声明的变量,该变量用来存放RealSubject角色的实例引用,代理的实例就可以控制对它所包含的RealSubject角色的实例访问,即可以控制对它所代理对象的访问。

代理模式UML类图:

代理模式优点:

(1) 代理模式可以屏蔽用户真正请求的对象,使用户程序和真正的对象之间的解耦。

(2) 使用代理来担当那些创建耗时的对象的替身。

代理模式应用情景:

(1) 程序可能不希望用户直接访问该对象,而是提供一个特殊的对象以控制对当前对象的访问。

(2) 如果一个对象(例如很大的图像)需要很长时间才能加载完成。

(3) 如果对象位于程序主机上,需要为用户提供访问该远程对象的能力。


14、中介者模式(Mediator Pattern):

用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显示地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。

Define an object that encapsulates how a set of objects interact. Mediator promotes loose coupling by keeping objects from referring to each other explicitly, and it lets you vary their interaction independently.

注意:中介者模式是封装一系列的对象交互的成熟模式,其关键是将对象之间的交互封装在称作中介者的对象中,中介者使各对象不需要显示地相互引用,这些对象只包含中介者的引用。

模式结构:

中介者(Mediator):中介者是一个接口,该接口定义了用于同事对象之间进行通信的方法。

具体中介者(ConcreteMediator):具体中介者是实现中介者接口的类。具体中介者需要包含所有具体同事的引用,并通过实现中介者接口中的方法来满足具体同事之间的通信请求。

同事(Colleague):一个接口,规定了具体同事需要实现的方法。

具体同事(ConcreteColleague):实现同事接口的类。具体同事需要包含具体中介者的引用,一个具体同事需要和其他具体同事交互时,只需将自己的请求通知给它所包含的具体中介者即可。

中介者模式UML类图:

中介者模式优点:

(1) 可以避免许多对象为了之间的通信而相互显示引用,否则,不仅系统难于维护,而且也使其他系统难以复用这些对象。

(2) 可以通过中介者将原本分布于多个对象之间的交互行为集中在一起。当这些对象之间需要改变之间的通信行为时,只需使用一个具体中介者即可,不必修改各个具体同事的代码,即这些同事可被重用。

(3) 具体中介者使得各个具体同事完全解耦,修改任何一个具体同事的代码不会影响到其他同事。

(4) 具体中介者集中了同事之间是如何交互的细节,使系统比较清楚地知道整个系统中的同事是如何交互的。

(5) 当一些对象想互相通信,但又无法相互包含对方的引用,那么使用中介者模式就可以使这对象互相通信。

中介者应用情景:

(1) 许多对象以复杂的方式交互,所导致的依赖关系使系统难以理解和维护。

(2) 一个对象引用其他很多对象,导致难以复用该对象。




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值