装饰模式
把原本的对象传进来,增加新的功能。而不是通过子类的方式,也可以装饰套装饰。
装饰模式又叫做包装模式,通常一种对客户端透明的方式来扩展对象的功能,是继承关系的一个替换方案。
动态地给一个对象添加一些额外的职责。就增加功能来说,装饰器模式相比生成子类更为灵活。
主要解决:一般的,我们为了扩展一个类经常使用继承方式实现,由于继承为类引入静态特征,并且随着扩展功能的增多,子类会很膨胀。
装饰模式的结构
装饰模式的角色和职责
非装饰模式,通过子类添加功能
interface Car
{
public void show();
}
class RunCar implements Car
{
@Override
public void show() {
this.run();
}
public void run()
{
System.out.println("可以跑");
}
}
class SwimCar implements Car{
@Override
public void show() {
this.run();
this.swim();
}
public void run()
{
System.out.println("可以跑");
}
public void swim()
{
System.out.println("可以游");
}
}
class FlyCar implements Car
{
public void fly()
{
System.out.println("可以飞");
}
@Override
public void show() {
this.run();
this.fly();
}
public void run()
{
System.out.println("可以跑");
}
}
public class MainClass
{
public static void main(String[] args) {
Car car = new FlyCar();
car.show();
}
}
输出
可以跑
可以飞
通过装饰模式
interface Car
{
public abstract void show();
public abstract void run();
}
class RunCar implements Car{
@Override
public void show()
{
this.run();
}
public void run()
{
System.out.println("可以跑");
}
}
abstract class CarDecorator implements Car
{
private Car car;
public Car getCar() {
return car;
}
public void setCar(Car car) {
this.car = car;
}
public CarDecorator(Car car) {
this.car = car;
}
public abstract void show();
}
class FlyCarDecorator extends CarDecorator
{
public FlyCarDecorator(Car car) {
super(car);
}
@Override
public void show() {
this.getCar().show();
this.fly();
}
@Override
public void run() {
}
public void fly()
{
System.out.println("可以飞");
}
}
class SwimCarDecorator extends CarDecorator
{
public SwimCarDecorator(Car car) {
super(car);
}
@Override
public void show()
{
this.getCar().show();
this.swim();
}
public void swim()
{
System.out.println("可以游");
}
@Override
public void run()
{
}
}
public class MainClass
{
public static void main(String[] args) {
Car car = new RunCar();
CarDecorator carDecorator = new FlyCarDecorator(car);
car = new SwimCarDecorator(carDecorator);
car.show();
}
}
输出
可以跑
可以飞
可以游
如果想要又可以跑,又可以游,只需要在跑的外面装饰游,或者游的外面装饰跑。而不需要创建新的类。
享元模式
结构型模式的一种,它通过与其他对象共享数据来减小内存占用。
享元模式的结构
代码
//享元角色
class MyCharacter
{
private char myChar;
public MyCharacter(char myChar) {
this.myChar = myChar;
}
public void disPlay()
{
System.out.println(myChar);
}
}
//享元工厂角色
class MyCharacterFactory
{
private Map<Character,MyCharacter> pool;
public MyCharacterFactory() {
this.pool = new HashMap<Character, MyCharacter>();
}
public MyCharacter getMyCharacter(Character character)
{
MyCharacter myChar = pool.get(character);
if(myChar == null)
{
myChar = new MyCharacter(character);
pool.put(character,myChar);
}
return myChar;
}
}
public class MainClass
{
public static void main(String[] args)
{
// MyCharacter myCharacter = new MyCharacter('a');
// MyCharacter myCharacter1 = new MyCharacter('b');
// MyCharacter myCharacter2 = new MyCharacter('a');
// MyCharacter myCharacter3 = new MyCharacter('d');
//
// myCharacter.disPlay();
// myCharacter1.disPlay();
// myCharacter2.disPlay();
// myCharacter3.disPlay();
// System.out.println(myCharacter==myCharacter2);//false
MyCharacterFactory myCharacterFactory = new MyCharacterFactory();
MyCharacter myCharacter = myCharacterFactory.getMyCharacter('a');
MyCharacter myCharacter1 = myCharacterFactory.getMyCharacter('b');
MyCharacter myCharacter2 = myCharacterFactory.getMyCharacter('a');
MyCharacter myCharacter3 = myCharacterFactory.getMyCharacter('b');
myCharacter.disPlay();
myCharacter1.disPlay();
myCharacter2.disPlay();
myCharacter3.disPlay();
System.out.println(myCharacter==myCharacter2); //true
System.out.println(myCharacter1==myCharacter3); //true
}
}
代理模式
在代理模式(Proxy Pattern)中,一个类代表另一个类的功能。这种类型的设计模式属于结构型模式。
在代理模式中,我们创建具有现有对象的对象,以便向外界提供功能接口。
介绍
-
意图:为其他对象提供一种代理以控制对这个对象的访问。
-
主要解决:在直接访问对象时带来的问题,比如说:要访问的对象在远程的机器上。在面向对象系统中,有些对象由于某些原因(比如对象创建开销很大,或者某些操作需要安全控制,或者需要进程外的访问),直接访问会给使用者或者系统结构带来很多麻烦,我们可以在访问此对象时加上一个对此对象的访问层。
-
何时使用:想在访问一个类时做一些控制。
-
如何解决:增加中间层。
-
关键代码:实现与被代理类组合。
实现
我们将创建一个 Image 接口和实现了 Image 接口的实体类。ProxyImage 是一个代理类,减少 RealImage 对象加载的内存占用。
ProxyPatternDemo,我们的演示类使用 ProxyImage 来获取要加载的 Image 对象,并按照需求进行显示。
interface Image {
void display();
}
class RealImage implements Image
{
private String fileName;
public RealImage(String fileName){
this.fileName = fileName;
loadFromDisk(fileName);
}
@Override
public void display() {
System.out.println("Displaying " + fileName);
}
private void loadFromDisk(String fileName){
System.out.println("Loading " + fileName);
}
}
class ProxyImage implements Image{
private RealImage realImage;
private String fileName;
public ProxyImage(String fileName){
this.fileName = fileName;
}
@Override
public void display() {
if(realImage == null){
realImage = new RealImage(fileName);
}
realImage.display();
}
}
public class ProxyPatternDemo {
public static void main(String[] args) {
Image image = new ProxyImage("test_10mb.jpg");
// 图像将从磁盘加载
image.display();
System.out.println("");
// 图像不需要从磁盘加载
image.display();
}
}
执行程序,输出结果:
Loading test_10mb.jpg
Displaying test_10mb.jpg
Displaying test_10mb.jpg
外观模式
外观模式(Facade Pattern)隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口。这种类型的设计模式属于结构型模式,它向现有的系统添加一个接口,来隐藏系统的复杂性。
介绍
-
意图:为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
-
主要解决:降低访问复杂系统的内部子系统时的复杂度,简化客户端与之的接口。
-
何时使用: 1、客户端不需要知道系统内部的复杂联系,整个系统只需提供一个"接待员"即可。 2、定义系统的入口。
-
如何解决:客户端不与系统耦合,外观类与系统耦合。
-
关键代码:在客户端和复杂系统之间再加一层,这一层将调用顺序、依赖关系等处理好。
-
应用实例: 1、去医院看病,可能要去挂号、门诊、划价、取药,让患者或患者家属觉得很复杂,如果有提供接待人员,只让接待人员来处理,就很方便。 2、JAVA 的三层开发模式。
-
优点: 1、减少系统相互依赖。 2、提高灵活性。 3、提高了安全性。
-
缺点:不符合开闭原则,如果要改东西很麻烦,继承重写都不合适。
外观模式结构
代码
class SystemA
{
public void doSomething()
{
System.out.println("实现A系统功能");
}
}
class SystemB
{
public void doSomething()
{
System.out.println("实现B系统功能");
}
}
class SystemC
{
public void doSomething()
{
System.out.println("实现C系统功能");
}
}
class Facade
{
private SystemA systemA;
private SystemB systemB;
private SystemC systemC;
public Facade()
{
systemA = new SystemA();
systemB = new SystemB();
systemC = new SystemC();
}
public void doSomethingA()
{
systemA.doSomething();
}
public void doSomethingB()
{
systemB.doSomething();
}
public void doSomethingC()
{
systemC.doSomething();
}
}
public class MainClass
{
public static void main(String[] args) {
Facade facade = new Facade();
facade.doSomethingA();
}
}
组合模式
通过递归手段来构造树形的对象结构,并可以通过一个对象来访问整个树。
组合模式依据树形结构来组合对象,用来表示部分以及整体层次
组合模式结构
/**
* 文件和目录的父类
*/
interface IFile
{
//显示文件或者文件夹的名称
public void display();
//添加
public boolean add(IFile file);
//移除
public boolean remove(IFile file);
//获得子节点
public List<IFile> getChild();
}
/**
* 目录
*/
class Folder implements IFile
{
String name;
private List<IFile> children;
public Folder(String name) {
this.name = name;
children = new ArrayList<>();
}
@Override
public void display() {
System.out.println(name);
}
@Override
public boolean add(IFile file) {
return children.add(file);
}
@Override
public boolean remove(IFile file) {
return children.remove(file);
}
@Override
public List<IFile> getChild() {
return children;
}
}
//文件,相当于叶子节点
class File implements IFile
{
private String name;
public File(String name)
{
this.name = name;
}
@Override
public void display() {
System.out.println(name);
}
@Override
public boolean add(IFile file) {
return false;
}
@Override
public boolean remove(IFile file) {
return false;
}
@Override
public List<IFile> getChild() {
return null;
}
}
public class MainClass
{
public static void main(String[] args)
{
//C盘
Folder rootFolder = new Folder("C:");
//beifeng目录
Folder beifengFolder = new Folder("beifeng");
//文件
File file = new File("beifeng.txt");
rootFolder.add(beifengFolder);
rootFolder.add(file);
displayTree(rootFolder);
}
public static void displayTree(IFile rootFolder)
{
//显示自身名称
rootFolder.display();
//获得子树
List<IFile> child = rootFolder.getChild();
for(IFile file:child)
{
if(file instanceof File)
file.display();
else
displayTree(file);
}
}
}