复习一下,之前说的都是创建型模式
有工厂三家族,简单工厂,工厂方法,抽象工厂
简单工厂是一个作坊里产一款产品
工厂方法是一个大作坊有几个小作坊,每个小作坊产一款产品
抽象工厂是一个大作坊有几个小作坊,每个小作坊产不同系列的一部分。最后产一系列的产品
建造者是老板管搞论文的和搞工程的,搞工程的就是几个架构搭建,搞论文的就是搞些公式和结果图搞,最后来到实验室找到老板就知道实验室有什么东西了
享元是简历复制。把要改的改了。争取共享一些东西。
单例就是一个家庭只能生一个孩子。没有的时候创建一个,有了的话,你来我家查孩子,就带你找那个独苗。数据库里面建立连接,就是这种模式的体现。
以上粗俗的话主要为了方便理解和回忆,请勿当真。。。。
推荐一下个人GitHub,里面有设计模式的源码 https://github.com/tori22/DesignPattern
(竟然是HTTPS协议的)
今天学习结构型模式
一.适配器
将一个类的接口转换成客户希望的另外一个接口。适配器模式使得原本由于
接口不兼容而不能一起工作的那些类可以一起工作。
优点:
通过适配器,客户端可以调用同一接口,因而对客户端来说是透明的。这样做更简单、更直接、更紧凑。
复用了现存的类,解决了现存类和复用环境要求不一致的问题。
将目标类和适配者类解耦,通过引入一个适配器类重用现有的适配者类,而无需修改原有代码。
一个对象适配器可以把多个不同的适配者类适配到同一个目标,也就是说,
同一个适配器可以把适配者类和它的子类都适配到目标接口。
缺点:
对于对象适配器来说,更换适配器的实现过程比较复杂。
适用场景:
系统需要使用现有的类,而这些类的接口不符合系统的接口。
想要建立一个可以重用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作。
两个类所做的事情相同或相似,但是具有不同接口的时候。
旧的系统开发的类已经实现了一些功能,但是客户端却只能以另外接口的形式访问,
但我们不希望手动更改原有类的时候。
使用第三方组件,组件接口定义和自己定义的不同,不希望修改自己的接口,但是要使用第三方组件接口的功能。
package AdapterPattern; public class Adaptee { public void specificRequest() { System.out.println("特殊请求!"); } } package AdapterPattern; public class Adapter extends Target { private Adaptee adaptee = new Adaptee(); @Override public void request() { adaptee.specificRequest(); } } package AdapterPattern; public class Client { public static void main(String[] args) { Target target = new Adapter(); target.request(); } } package AdapterPattern; public class Target { public void request() { System.out.println("普通请求"); } }
二.桥接
将抽象不笨与它的实现部分分离,使它们都可以独立地变化.
桥接模式的使用场景:
1、当一个对象有多个变化因素的时候,通过抽象这些变化因素,将依赖具体实现,修改为依赖抽象。
2、当某个变化因素在多个对象中共享时。我们可以抽象出这个变化因素,然后实现这些不同的变化因素。
3、当我们期望一个对象的多个变化因素可以动态的变化,而且不影响客户的程序的使用时。
8.组合(合成):
将对象组合成树形结构以表示‘部分-整体’的层次结构,组合模式使得用户
对单个对象和组合对象的使用具有一致性。
使用场景:
当发现需求中是体现部分与整体层次结构时,以及你希望用户可以忽略组合对象与单个对象的不同,
统一地使用组合结构中的所有对象时,就应该考虑组合模式了。
package BridgePattern; public class Abstraction { protected Implementor mImplementor; public void setImplementor(Implementor implementor) { mImplementor = implementor; } public void operation() { mImplementor.operation(); } } package BridgePattern; public class Client { public static void main(String[] args) { Abstraction ab = new RefinedAbstraction(); ab.setImplementor(new ConcrateImplementorA()); ab.operation(); ab.setImplementor(new ConcrateImplementorB()); ab.operation(); } } package BridgePattern; public class ConcrateImplementorA extends Implementor { @Override public void operation() { System.out.println("具体实现A的方法执行"); } } package BridgePattern; public class ConcrateImplementorB extends Implementor { @Override public void operation() { System.out.println("具体实现B的方法执行"); } } package BridgePattern; public abstract class Implementor { public abstract void operation(); } package BridgePattern; public class RefinedAbstraction extends Abstraction { @Override public void operation() { mImplementor.operation(); } }
三.组合
package CompositePattern; public class Client { public static void main(String[] args) { Composite root = new Composite("root"); root.add(new Leaf("Leaf A")); root.add(new Leaf("Leaf B")); Composite comp = new Composite("Composite X"); comp.add(new Leaf("Leaf XA")); comp.add(new Leaf("Leaf XB")); root.add(comp); Composite comp2 = new Composite("Composite XY"); comp2.add(new Leaf("Leaf XYA")); comp2.add(new Leaf("Leaf XYB")); comp.add(comp2); root.add(new Leaf("Leaf C")); Leaf leaf = new Leaf("Leaf D"); root.add(leaf); root.remove(leaf); root.display(1); } } package CompositePattern; public abstract class Component { protected String mName; public Component(String name) { mName = name; } public abstract void add(Component c); public abstract void remove(Component c); public abstract void display(int depth); } package CompositePattern; import java.util.ArrayList; import java.util.List; public class Composite extends Component { private List<Component> childern = new ArrayList<>(); public Composite(String name) { super(name); } @Override public void add(Component c) { childern.add(c); } @Override public void remove(Component c) { childern.remove(c); } @Override public void display(int depth) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < depth ; i++) { sb.append("-"); } System.out.println(sb.append(mName).toString()); for (Component c:childern) { c.display(depth+2); } } } package CompositePattern; public class Leaf extends Component{ public Leaf(String name) { super(name); } @Override public void add(Component c) { System.out.println("cannot add to a leaf"); } @Override public void remove(Component c) { System.out.println("cannot remove to a leaf"); } @Override public void display(int depth) { StringBuilder stringBuilder = new StringBuilder(); for (int i = 0; i < depth ; i++) { stringBuilder.append("-"); } System.out.println(stringBuilder.append(mName).toString()); } }
四.装饰
动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式相比生成子类更加灵活。
1.在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。
2 处理那些可以撤消的职责。
3.当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,
为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。
另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。
package DecoratorPattern; public abstract class Component { public abstract void Opeartion(); } package DecoratorPattern; public class ConcreateComponent extends Component { @Override public void Opeartion() { System.out.println("具体对象的操作"); } } package DecoratorPattern; public class ConcreateDecoratorA extends Decorator{ public String addedState; @Override public void Opeartion() { super.Opeartion(); addedState = "New State"; System.out.println("具体装饰对象A的操作" + addedState); } } package DecoratorPattern; public class ConcreateDecoratorB extends Decorator{ @Override public void Opeartion() { super.Opeartion(); addedBehavior(); System.out.println("具体装饰对象B" ); } private void addedBehavior() { } } package DecoratorPattern; public abstract class Decorator extends Component { protected Component mcomponent; public void setcomponent(Component component) { mcomponent = component; } @Override public void Opeartion() { if (mcomponent != null) { mcomponent.Opeartion(); } } } package DecoratorPattern; public class Test { public static void main(String[] args) { ConcreateComponent component = new ConcreateComponent(); ConcreateDecoratorA decoratorA = new ConcreateDecoratorA(); ConcreateDecoratorB decoratorB = new ConcreateDecoratorB(); decoratorA.setcomponent(component); decoratorB.setcomponent(decoratorA); decoratorB.Opeartion(); } }
五.外观
为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,
这个接口使得这一子系统更加容易使用。
适用环境:
在开发阶段,子系统往往因为不断的重构演化而变得越来越复杂,
增加外观Facade可以提供一个简单的接口,减少它们之间的依赖.
在维护一个遗留的大型系统时,可能这个系统已经非常难以维护和扩展了,可以为
新系统开发一个外观Facade类,来提供设计粗糙或高度复杂的遗留代码的比较清晰
简单的接口,让新系统与Facade对象交互,Facade与遗留代码交互所有复杂的工作。
优点:
实现了子系统与客户端之间的松耦合关系。
客户端屏蔽了子系统组件,减少了客户端所需处理的对象数目,并使得子系统使用起来更加容易
package FacedePattern; public class Client { public static void main(String[] args) { Facede facede = new Facede(); facede.methodA(); facede.methodB(); } } package FacedePattern; public class Facede { private SubSystemOne one; private SubSystemTwo two; private SubSystemThree three; private SubSystemFour four; public Facede() { one = new SubSystemOne(); two = new SubSystemTwo(); three = new SubSystemThree(); four = new SubSystemFour(); } public void methodA() { System.out.println("方法组A------"); one.methodOne(); two.methodTwo(); four.methodFour(); } public void methodB() { System.out.println("方法组B----------"); two.methodTwo(); three.methodThree(); } } package FacedePattern; public class SubSystemFour { public void methodFour() { System.out.println("子系统方法四"); } } package FacedePattern; public class SubSystemOne { public void methodOne() { System.out.println("子系统方法一"); } } package FacedePattern; public class SubSystemThree { public void methodThree() { System.out.println("子系统方法三"); } } package FacedePattern; public class SubSystemTwo { public void methodTwo() { System.out.println("子系统方法二"); } }
六.享元
为运用共享技术有效地支持大量细粒度的对象。
优点:
1、享元模式的优点在于它能够极大的减少系统中对象的个数。
2、享元模式由于使用了外部状态,外部状态相对独立,不会影响到内部状态,
所以享元模式使得享元对象能够在不同的环境被共享。
缺点
1、由于享元模式需要区分外部状态和内部状态,使得应用程序在某种程度上来说更加复杂化了。
2、为了使对象可以共享,享元模式需要将享元对象的状态外部化,而读取外部状态使得运行时间变长。
模式适用场景
1、如果一个系统中存在大量的相同或者相似的对象,由于这类对象的大量使用,会造成系统内存的耗费,
可以使用享元模式来减少系统中对象的数量。
2、对象的大部分状态都可以外部化,可以将这些外部状态传入对象中。
package FlyweightPattern; public class Client { public static void main(String[] args) { int extrinsicstate = 22; FlyweightFactory factory = new FlyweightFactory(); Flyweight fx = factory.getFlyweight("x"); fx.operation(--extrinsicstate); Flyweight fy = factory.getFlyweight("y"); fy.operation(--extrinsicstate); Flyweight fz = factory.getFlyweight("z"); fz.operation(--extrinsicstate); Flyweight uf = new UnsharedConcreteFlyweight(); uf.operation(--extrinsicstate); } } package FlyweightPattern; public class ConcreteFlyweight extends Flyweight{ @Override public void operation(int extrinsicstate) { System.out.println(String.format("具体Flyweight:%s",extrinsicstate)); } } package FlyweightPattern; public abstract class Flyweight { public abstract void operation(int extrinsicstate); } package FlyweightPattern; import java.util.Hashtable; public class FlyweightFactory { private Hashtable flyweight = new Hashtable(); public FlyweightFactory() { flyweight.put("x",new ConcreteFlyweight()); flyweight.put("y",new ConcreteFlyweight()); flyweight.put("z",new ConcreteFlyweight()); } public Flyweight getFlyweight(String key) { return (Flyweight)flyweight.get(key); } } package FlyweightPattern; public class UnsharedConcreteFlyweight extends Flyweight { @Override public void operation(int extrinsicstate) { System.out.println(String.format("不共享的具体Flyweight:%d",extrinsicstate)); } }
七.代理
为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用
另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
代理模式常被分为远程代理、虚拟代理、保护代理等等。
优点:
1)代理模式能将代理对象与真正被调用的对象分离,在一定程度上降低了系统的耦合度。
2)代理模式在客户端和目标对象之间起到一个中介作用,这样可以起到保护目标对象的作用。
代理对象也可以对目标对象调用之前进行其他操作。
缺点:
1)在客户端和目标对象增加一个代理对象,会造成请求处理速度变慢。
2)增加了系统的复杂度。
使用场景:
1)远程代理,也就是为一个对象在不同的地址空间提供局部代表。这样可以隐藏一个对象存在于
不同地址空间的事实。
2)虚拟代理,根据需要创建开销很大的对象。通过它来存放实例化需要很长时间的对象。
3)安全代理,用来控制真实对象访问时的权限。
4)智能指引,当调用目标对象时,代理可以处理其他的一些操作。
package ProxyPattern; public class Client { public static void main(String[] args) { Proxy proxy = new Proxy(); proxy.request(); } } package ProxyPattern; public class Proxy extends Subject { private RealSubject mRealSubject; @Override public void request() { if (mRealSubject == null) { mRealSubject = new RealSubject(); } mRealSubject.request(); } } package ProxyPattern; public class RealSubject extends Subject { @Override public void request() { System.out.println("真实请求"); } } package ProxyPattern; public abstract class Subject { public abstract void request(); }