目录
1.桥接模式
2.装饰模式
3.外观模式
4.享元模式
5.组合模式
5.1透明方式
5.2安全方式
三、桥接模式(Bridge)
处理多层的继承结构,处理多维度变化的场景,将各个维度设置成独立的继承结构,使维度可以独立的扩展在抽象层建立关联。从而降低了抽象和实现这两个可变维度的耦合度。主要特点是,取消多继承,解决多维度的问题。
核心角色:
- (1)抽象化角色(Abstraction):定义抽象类,并包含一个对实例化对象的引用。
- (2)扩展抽象化角色(Refined Abstraction):是抽象化角色的子类,实现父类中的业务方法,并通过组合关系调用实现化角色中的业务方法。
- (3)实现化角色(Implementor):定义实现化角色的接口,供扩展抽象化角色调用。
- (4)具体实现化(Concrete Implementor):给出实现化角色接口的具体实现。
优点:
- (1)由于抽象与实现分离,所有扩展能力强。
- (2)其实现细节对客户透明。
缺点:
- (1)由于聚合关系在抽象层,要求开发者针对抽象化进行设计与编程,增加了系统的理解和设计难度。
public class textBridge {
public static void main(String[] args) {
// TODO Auto-generated method stub
//模拟:电脑有分品牌、分台式笔记本、配置等等。(涉及到多维度)
Implementor imple = new ConcreatelmplementorA();//创建第一个品牌
Abstraction abs = new RefinedAbstraction(imple);
abs.Operation();
}
}
//实现化角色。
interface Implementor{//品牌
public void Operationlmpl();
}
//具体实现化角色
class ConcreatelmplementorA implements Implementor{ //联想品牌
@Override
public void Operationlmpl() {
System.out.println("联想");
}
}
class ConcreatelmplementorB implements Implementor{//宏基品牌
@Override
public void Operationlmpl() {
System.out.println("宏基");
}
}
//抽象化角色
abstract class Abstraction{//电脑的台式或笔记本
protected Implementor imple;//为了子类可以使用
protected Abstraction(Implementor imple) {
this.imple = imple;
}
public abstract void Operation();//得到实现化角色的品牌
}
//扩展抽象化角色
class RefinedAbstraction extends Abstraction{
protected RefinedAbstraction(Implementor imple) {
super(imple);
}
@Override
public void Operation() {
imple.Operationlmpl();//一个维度:品牌
System.out.println("台式机");//当前扩展一个维度:表现形式
}
}
二、装饰模式(Decorator)
可以动态的为对象添加新的功能,是一种用于代替继承的技术,无须通过继承添加子类就能扩展对象的新功能。使用对象的关联关系代替继承关系。同时避免类型体系的快速膨胀。
核心角色:
- (1)抽象构件角色(Component):定义一个抽象的接口以规范准备接收附加责任的对象。
- (2)具体构件角色(Concrete Component):实现抽象化构件,通过装饰角色为其添加一些职责。
- (3)抽象装饰角色(Decorator):实现抽象构件,并包含具体构件的实例。可以通过其子类扩展具体构件的功能。
- (4)具体装饰角色(Concrete Decorator):继承抽象装饰的相关方法,并给具体构件对象添加附加的责任。
优点:
- (1)装饰模式扩展的功能比继承方式要灵活。
- (2)可以设计出多个不同的具体装饰类,创建出不同行为的组合。
缺点:
- (1)装饰模式增加了许多子类,如果过度使用会使程序变得很复杂。
public class textDecorator {
public static void main(String[] args) {
// TODO Auto-generated method stub
//原来的功能
Component car = new ConcreteComponent();
car.operation();
//进过装饰
Component carbefore = new ConcreteDecorator(car);
carbefore.operation(); //装饰了新的功能
}
}
//模拟一个车的改装
//抽象构件角色
interface Component{//车,能开
public void operation();
}
//具体构件角色
class ConcreteComponent implements Component{
@Override
public void operation() {
System.out.println("奥迪可以在陆地上飞快的行驶。");
}
}
//抽象装饰角色
class Decorator implements Component{
private Component component;
public Decorator(Component component) {
this.component = component;
}
@Override
public void operation() {//获取到原来的功能
component.operation();
}
}
//具体装饰角色
class ConcreteDecorator extends Decorator{
public ConcreteDecorator(Component component) {
super(component);
}
public void operation() {
super.operation();//继承拿到原来的功能
addedFunction();//装饰新的功能
}
//新的功能
public void addedFunction() {
System.out.println("添加的功能:会飞");
}
}
三、外观模式(Facade)
为系统提供统一的入口,封装系统的复杂性,便于客户端的使用。
核心角色:
- (1)外观角色(Facade):为多个子系统对外提供一个共同的接口。
- (2)子系统角色(Sub System):实现系统的部分功能,客户可以通过外观角色访问它。
- (3)客户角色(Client):通过外观访问角色访问各个子系统的功能。
优点:(迪米特原则的典型应用)
- (1)降低子系统与客户端的耦合度,使得子系统的变化不会影响调用它的客户类。
- (2)可客户屏蔽了子系统组件,减少了客户处理的对象数目,使用更容易。
- (3)降低了大型软件系统的编译依赖性,简化了系统在不同平台的移植过程。
缺点:
- (1)不能很好地限制客户使用子系统。
- (2)增加新的子系统时,可能需要改变外观类或客户端源代码,违背了开闭原则
public class textFacade {
public static void main(String[] args) {
// TODO Auto-generated method stub
//现在所有的流程都需要在一个门面里面就可以操作了
Facade f = new Facade();
f.method();
}
}
//模拟:身份证的办理
class Facade{
private SubSystem01 obj1 = new SubSystem01();//拍照
private SubSystem02 obj2 = new SubSystem02();//复印件
private SubSystem03 obj3 = new SubSystem03();//上传拿回执
public void method() {//门面统一操作
obj1.method1();
obj2.method2();
obj3.method3();
}
}
//子系统
class SubSystem01{
public void method1() {
System.out.println("统一拍照");
}
}
class SubSystem02{
public void method2() {
System.out.println("统一打印复印件");
}
}
class SubSystem03{
public void method3() {
System.out.println("统一上传,打印回执");
}
}
三、享元模式(Flyweight)
运用共享的技术高效的支持大量细粒度对象的重用。通过共享已经存在的对象来减少大量需要创建的对象数量。从而提高系统资源的利用率。
享元模式能做到共享的关键:区分内部和外部的状态。
内部状态可以共享,不会随着环境的变化而变化。外部状态则反之。
核心角色:
- (1)抽象享元角色(Flyweight):是所有的具体享元类的基类,为具体享元规范需要实现的公共接口,非享元的外部状态以参数的形式通过方法传入。
- (2)具体享元角色(Concrete Flyweight):实现抽象享元角色中规定的接口
- (3)非享元角色(Unsharable Flyweight):是不可以共享的外部状态,以参数的形式注入具体享元的相关方法中
- (4)享元工厂角色(Flyweight Factory):负责创建和管理享元角色。当客户对象请求一个享元对象时,享元工厂检查系统中是否有符合要求的享元对象,如果存在则提供给客户,反之,创建一个新的享元对象。
优点:
- (1)相同的对象只要保存一份,这降低了系统中对象的数量,从而降低了系统中细粒度对象给内存的压力。
缺点:
- (1)为了使用对象可以共享,需要将一些不共享的状态外部化,增加了程序的复杂性。
- (2)读取享元模式的外部状态会使得运行时间稍微变长。
public class textFlyweight {
public static void main(String[] args) {
// TODO Auto-generated method stub
//像一幅棋子中,棋子的颜色、大小等都是可以共享的。
FlyweightFactory factory = new FlyweightFactory();
Flyweight f01 = factory.getFlyweight("白色棋子");//创建享元对象
Flyweight f02 = factory.getFlyweight("白色棋子");//创建享元对象
Flyweight f03 = factory.getFlyweight("黑色棋子");//创建享元对象
f01.operation(new UnsharedConcreteFlyweight("棋子《车》"));
f03.operation(new UnsharedConcreteFlyweight("棋子《车》"));
}
}
//模拟:一个棋盘上的棋子的大小和颜色是可以共享的。位置是不可以共享的。
//抽象享元角色
interface Flyweight{
public void operation(UnsharedConcreteFlyweight state);
}
//非享元角色
class UnsharedConcreteFlyweight{
private String info;
public UnsharedConcreteFlyweight(String info) {
this.info = info;
}
public String getInfo() {
return info;
}
public void setInfo(String info) {
this.info = info;
}
}
//具体享元角色
class ConcreteFlyweight implements Flyweight{
private String key;
public ConcreteFlyweight(String key) {
this.key = key;
System.out.println("具体享元<"+key+">被创建");
}
@Override
public void operation(UnsharedConcreteFlyweight outState) {
System.out.print("具体享元<"+key+">被调用,");
System.out.println("非享元信息<"+outState.getInfo()+">");
}
}
//享元工厂角色
class FlyweightFactory{
private HashMap<String, Flyweight> flyweights = new HashMap<String, Flyweight>();
public Flyweight getFlyweight(String key) {
Flyweight flyweight = flyweights.get(key);
if(flyweight != null) {
System.out.println("具体享元<"+key+">已经存在,被成功获取");
}else {
flyweight = new ConcreteFlyweight(key);
flyweights.put(key, flyweight);
}
return flyweight;
}
}
五、组合模式(Composite)
把部分和整体的关系用树形结构来表示,从而使客户端可以使用统一的方式去处理部分对象和整体对象。
可以分为:透明方式、安全方式。
核心角色:
- (1)抽象构件角色(Component):为树叶构件和树枝构件声明公共接口,并实现它们的默认行为。在透明式中,抽象构件还声明访问和管理子类的接口。在安全式中,不声明访问和管理子类的接口,管理工作由树枝完成。
- (2)树叶构件角色(Leaf):是组合中的叶节点对象,它没有子节点,用于实现抽象构件角色中声明的公共接口。
- (3)树枝构件角色(Composite):是组合中的分支节点对象,有子节点。实现了抽象构件角色中声明的公共接口,主要作用是存储和管理子部件,通常包含Add()、Remove()、GeChild()等方法。
优点:
- (1)使得客户端可以一致的处理单个对象和组合对象,无需关心自己处理的是单个对象还是组合对象,简化了客户端代码。
- (2)更容易在组合体内加入新对象,客户端不会因为加入了新的对象而更改源代码,满足开闭原则。
缺点:
- (1)设计复杂,客户端需要花更多的时间理清类之间的层次关系。
- (2)不容易限制容器中的构件。
- (3)不容易用继承的方法来增加构件的新工能。
透明方式
由于抽象构件声明了所有子类中的全部方法,所以客户端无须区别树叶对象和树枝对象,对客户端来说是透明的。但是缺点是:树叶构件本来没有Add()、Remove()、GetChild()方法,却要实现它们(空实现或抛异常),这样会带来一下安全性问题。
public class textComposite {
public static void main(String[] args) {
// TODO Auto-generated method stub
Component cp1 = new Composite();//树枝构件
Component cp2 = new Composite();
Component lef1 = new Leaf("树叶1");//树叶
Component lef2 = new Leaf("树叶2");
Component lef3 = new Leaf("树叶3");
cp1.add(lef1); //树枝上添加树叶
cp1.add(lef2);
cp1.add(cp2); //树枝上添加树枝
cp2.add(lef3);
cp1.operation();//访问
}
}
//抽象构件
interface Component{
public void add(Component c); //添加构件
public void remove(Component c);//删除构件
public Component getChild(int i);//获取构件
public void operation();//访问
}
//树叶构件
class Leaf implements Component{
private String name;
public Leaf(String name) {
this.name = name;
}
@Override
public void add(Component c) {}
@Override
public void remove(Component c) {}
@Override
public Component getChild(int i) {
return null;
}
@Override
public void operation() {
System.out.println("树叶<"+name+">被访问");
}
}
//树枝构件
class Composite implements Component{
private ArrayList<Component> children = new ArrayList<Component>();
@Override
public void add(Component c) {
children.add(c);
}
@Override
public void remove(Component c) {
children.remove(c);
}
@Override
public Component getChild(int i) {
return children.get(i);
}
@Override
public void operation() {
for (Object obj : children) {
((Component) obj).operation();
}
}
}
安全方式
将管理子构件的方法移到树枝构件中,避免上一种方式的安全性问题。由于叶子和分支有不同的接口,客户端在调用时要知道树叶对象和树枝对象的存在,失去了透明性。
public class textComposite {
public static void main(String[] args) {
// TODO Auto-generated method stub
Composite cp1 = new Composite();//树枝构件
Composite cp2 = new Composite();
Component lef1 = new Leaf("树叶1");//树叶
Component lef2 = new Leaf("树叶2");
Component lef3 = new Leaf("树叶3");
cp1.add(lef1); //树枝上添加树叶
cp1.add(lef2);
cp1.add(cp2); //树枝上添加树枝
cp2.add(lef3);
cp1.operation();//访问
}
}
//抽象构件
interface Component{
public void operation();//访问
}
//树叶构件
class Leaf implements Component{
private String name;
public Leaf(String name) {
this.name = name;
}
@Override
public void operation() {
System.out.println("树叶<"+name+">被访问");
}
}
//树枝构件
class Composite implements Component{
private ArrayList<Component> children = new ArrayList<Component>();
public void add(Component c) {
children.add(c);
}
public void remove(Component c) {
children.remove(c);
}
public Component getChild(int i) {
return children.get(i);
}
@Override
public void operation() {
for (Object obj : children) {
((Component) obj).operation();
}
}
}