装饰模式
Decoration Pattern。
主要解决:一般的,我们为了扩展一个类经常使用继承方式实现,由于继承为类引入静态特征,并且随着扩展功能的增多,子类会很膨胀。
定义
动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式比生成子类更为灵活。
装饰模式有以下4个角色:
- 抽象构建(Component)角色:该角色用于规范需要装饰地对象(原始对象)。
- 具体构建(Concrete Component)角色:该角色实现抽象构建接口,定义一个需要装饰的原始类。
- 装饰(Decorator)角色:该角色持有一个构建对象的实例,并定义一个与抽象构建接口一致的接口。
- 具体装饰(Concrete Decorator)角色:该角色负责对构建啊对象进行装饰。
应用
- 优缺点:
1)装饰类和被装饰类可以独立发展,而不会相互耦合。
2)装饰模式是继承关系的一个替代方案。装饰类Decorator,不管装饰多少层,返回的对象还是Component。
3)装饰模式可以动态地扩展一个实现类的功能。
4)缺点:多层装饰比较复杂。 - 使用场景:
1)需要扩展一个类的功能,或给一个类增加附加功能。
2)需要动态地给一个对象增加功能,这些功能可以再动态地撤销。
3)需要为一批类进行改装或加装功能。
实例
通过对裸车进行装饰的过程演示装饰模式的应用。
Car.java
//Component
public interface Car{
//车的装配
public void show();
}
Benz.java//ConcreteComponent
//奔驰车(裸车,需要装饰)
public class Benz implements Car{
public void show(){
System.out.println("奔驰车的默认颜色是黑色");
}
}
CarDecorator.java//Decorator
//汽车装饰
public abstract class CarDecorator implements Car{
private Car car=null;
public CarDecorator(Car car){
this.car=car;
}
public void show(){
this.car.show();
}
}
ConcreteCarDecorator.java
//具体汽车装饰
public class ConcreteCarDecorator extends CarDecorator{
public ConcreteCarDecorator(Car car){
super(car);
}
//给车进行彩绘
private void print(){
System.out.println("在车尾绘制“新手”字样,颜色是紫色");
}
//
private void setGps(){
System.out.println("安装GPS定位导航系统");
}
//
public void show(){
super.show();
this.print();
this.setGps();
}
}
ClientDemo.java
public class ClientDemo{
public static void main(String args[]){
Car car=new Benz();
CarDecoration cd=new ConcreteCarDecorator(car);
cd.show();
}
}
运行结果如下所示
奔驰车的默认颜色是黑色
在车尾绘制“新手”字样,颜色是紫色
安装GPS定位导航系统
工厂模式
工厂方法模式(Factory Method Pattern)又叫虚拟构造函数(Virtual Constructor)模式或者多态性工厂(Polymorphic Factory)模式。工厂方法模式的用意是定义一个创建产品对象的工厂接口,将实际创建性工作推迟到子类中。
主要解决:主要解决接口选择的问题。
定义
定义一个用于创建对象的接口,让子类决定实例化哪个类。工厂方法使一个类的实例化延迟到其子类。
在工厂方法模式中,共涉及以下4个角色:
- 抽象工厂(Creator)角色:该角色使工厂方法模式的核心,与应用系统无关,任何在创建对象的工厂类必须实现这个接口。
- 具体工厂(Concrete Creator)角色:该角色实现了抽象工厂接口,含有与应用密切相关的逻辑,并且受到应用程序的调用以创建产品对象。
- 抽象产品(Product)角色:该角色负责定义产品的共性,实现对产品最抽象的定义。
- 具体产品(Concrete Product)角色:该角色实现抽象产品角色所声明的接口,工厂方法模式所创建的每一个对象都是某个具体产品角色的实例。
应用
- 优点:
1)良好的封装性,代码结构清晰。
2)优秀的可扩展性。
3)屏蔽产品类。产品类的实现如何变化,调用者都不需要关心,而只需要关心产品的接口,只要产品接口保持不变,系统的上层模块就不需要发生变化。
4)工厂方法模式是典型的解耦框架。 - 缺点:
每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。 - 使用场景:
1)工厂方法模式是new一个对象的替代品,因此在所有需要生成对象的地方都可以使用,但是需要慎重考虑是否需要增加一个工厂类进行管理,增加代码的复杂度。
2)需要灵活的、可扩展的框架时,可以考虑采用工厂方法模式。
3)工厂方法模式可以用在异构项目中。
4)工厂方法模式可以使用在测试驱动开发的框架下。例如,测试一个类A,就需要 将与类A关联的类B也同时产生出来,使用工厂方法模式可以将类B虚拟出来, 避免类A与类B的耦合。
实例
通过农场系统演示工厂方法模式。
FruitGardener.java
public interface FruitGardener{
public Fruit factory();
}
Fruit.java
public interface Fruit{
public void grow();
public void harvest();
public void plant();
}
AppleGardener.java
public class AppleGardener implements FruitGardener{
public Fruit factory(){
return new Apple();
}
}
GrapeGardener.java
public class GrapeGardener implements FruitGardener{
public Fruit factory(){
return new Graph();
}
}
Apple.java
public class Apple implements Fruit{
private int treeAge;
public int getTreeAge(){
return treeAge;
}
public void setTreeAge(int treeAge) {
this.treeAge = treeAge;
}
public void grow() {
System.out.println("苹果正在生长...");
}
public void harvest() {
System.out.println("收获苹果");
}
public void plant() {
System.out.println("栽种苹果");
}
}
Grape.java
public class Grape implements Fruit{
private boolean seedless;
public bollean isseedless(){
return seedless;
}
public void setSeedless(boolean seedless){
this.seedless=seedless;
}
public void grow() {
System.out.println("葡萄正在生长...");
}
public void harvest() {
System.out.println("收获葡萄");
}
public void plant() {
System.out.println("栽种葡萄");
}
}
ClientDemo.java
public class ClientDemo{
public static void main(String[] args){
//苹果园丁工厂
FruitGardener fruitgardener=new AppleGardener();
//通过工厂生产苹果
Fruit apple=fruitgardener.factory();
apple.planet();
apple.grow();
apple.harvest();
//葡萄园丁工厂
fruitgardener=new GrapeGardener();
//通过工厂生产葡萄。
Fruit grape=fruitgardener.factory();
grape.plant();
grape.grow();
grape.harvest();
}
}
抽象工厂模式
Abstract Factory Pattern
主要解决:主要解决接口选择的问题
定义
为创建一组相关或相互依赖的对象提供一个接口,而且无须指定它们的具体类。
在有多个业务品种、业务分类时,通过抽象工厂模式产生需要的对象是一种非常好的解决方式。
抽象工厂模式中角色与工厂方法类似,也是有4个角色:
- 抽象工厂(Abstract Factory)角色:该角色是抽象工厂模式的核心,与应用系统无关,任何创建对象的工厂类必须实现这个接口。
- 具体工厂(Concrete Factory)角色:该角色实现了抽象工厂接口,含有选择合适的产品对象的逻辑,并且受到应用程序的调用以创建产品对象。
- 抽象产品(Abstract Product)角色:该角色负责定义产品的共性,实现对产品最抽象的定义。
- 具体产品(Concrete Product)角色:该角色实现抽象产品角色所声明的接口,抽象工厂模式所创建的任何产品对象都是某个具体产品角色的实例。
应用
- 优点:
1)产品族内的约束为非公开状态,在不同的工厂中,各种产品可能具有不同的相互依赖关系,这些依赖关系由工厂封装在其内部,对于工厂的使用者是不可见的。
2)生产线的扩展非常容易,如果针对同一产品族建立新的生产线,只需实现产品族中的所有产品接口并建立新的工厂即可。 - 缺点:产品族本身的扩展非常困难,如果需要在产品族中增加一个新的产品类型,则需要修改多个接口,并且会影响已有的工厂类。
最大的缺点是: - 使用场景:当一个对象族(或是一组没有任何关系的对象)都有相同的约束,则可以使用抽象工厂模式。
实例
AbstractWidgetFactory.java//AbstractFactory
public interface AbstractWidgetFactory{
public Window createWindow();
public Scrollbar createScrollbar();
}
WidgetFactory1.java//ConcreteFactory1
public class WidgetFactory1{
public Window createWindow(){
return new MSwindow();
}
public Scrollbar createScrollbar(){
A
}
}
WidgetFactory2.java//ConcreteFactory2
public class WidgetFactory2{
public Window createWindow(){
return new MotifWindow();
}
public Scrollbar createScrollbar{
B
}
}
Window.java//AbstractProductA
public interface Window{
public void setTitle(String s);
public void repaont();
public void addScrollbar(...);
}
PMWindow.java//ConcreteProductA1
public class PMWindow implements Window{
public void setTitle(){...}
public void repaint(){...}
}
MotifWindow.java//ConcreteProductA2
public class MotifWindow implements Window{
public void setTitle(){...}
public void repaint(){...}
}
GUIbuilder.java//辅助类
public class GUIBuilder{
public void buildWindow(AbstractWidgetFactory widgetFactory){
Window window=widgetFactory.createWindow();
Scrollbar scrollbar=widgetFactory.createScrollbar();
window.setTitle("New Window");
window.addScrollbar(scrollbar);
}
}
Client.java
public class Client{
public static void main(String args[]){
GUIBuilder builder=new GUIBuilder();
AbstractWidgeFactory widgetFactory=null;
if("MOtif")
widgetFactory=new WidgetFactory2();
else
widgetFactory=new WidgetFactory1();
builder.buildWindow(widgetFactory);
}
}